TenantAtlas/apps/platform/app/Support/Artifacts/ArtifactSourceDescriptor.php
Ahmed Darrazi bf8d59e034
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m36s
feat: implement provider-neutral artifact source taxonomy
2026-05-09 01:45:12 +02:00

122 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Artifacts;
use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;
/**
* @implements Arrayable<string, mixed>
*/
final readonly class ArtifactSourceDescriptor implements Arrayable, JsonSerializable
{
public function __construct(
public int $workspaceId,
public int $tenantId,
public int $managedEnvironmentId,
public string $sourceFamily,
public string $sourceKind,
public string $providerKey,
public ?int $providerConnectionId,
public string $sourceTargetKind,
public ?string $sourceTargetIdentifier,
public ?string $detectorKey,
public ?string $controlKey,
public ?int $packageRunId = null,
) {}
/**
* @param array<string, mixed> $payload
*/
public static function fromArray(array $payload): self
{
return new self(
workspaceId: max(0, (int) ($payload['workspace_id'] ?? 0)),
tenantId: max(0, (int) ($payload['tenant_id'] ?? $payload['managed_environment_id'] ?? 0)),
managedEnvironmentId: max(0, (int) ($payload['managed_environment_id'] ?? $payload['tenant_id'] ?? 0)),
sourceFamily: self::stringOrDefault($payload['source_family'] ?? null, ArtifactSourceTaxonomy::SOURCE_FAMILY_EVIDENCE_SNAPSHOT),
sourceKind: self::stringOrDefault($payload['source_kind'] ?? null, ArtifactSourceTaxonomy::SOURCE_KIND_MODEL_SUMMARY),
providerKey: self::stringOrDefault($payload['provider_key'] ?? null, 'microsoft'),
providerConnectionId: self::nullableInt($payload['provider_connection_id'] ?? null),
sourceTargetKind: self::stringOrDefault($payload['source_target_kind'] ?? null, ArtifactSourceTaxonomy::SOURCE_TARGET_MANAGED_ENVIRONMENT),
sourceTargetIdentifier: self::nullableString($payload['source_target_identifier'] ?? null),
detectorKey: self::nullableString($payload['detector_key'] ?? null),
controlKey: self::nullableString($payload['control_key'] ?? null),
packageRunId: self::nullableInt($payload['package_run_id'] ?? null),
);
}
/**
* @return array{
* workspace_id: int,
* tenant_id: int,
* managed_environment_id: int,
* source_family: string,
* source_kind: string,
* provider_key: string,
* provider_connection_id: ?int,
* source_target_kind: string,
* source_target_identifier: ?string,
* detector_key: ?string,
* control_key: ?string,
* package_run_id: ?int
* }
*/
public function toArray(): array
{
return [
'workspace_id' => $this->workspaceId,
'tenant_id' => $this->tenantId,
'managed_environment_id' => $this->managedEnvironmentId,
'source_family' => $this->sourceFamily,
'source_kind' => $this->sourceKind,
'provider_key' => $this->providerKey,
'provider_connection_id' => $this->providerConnectionId,
'source_target_kind' => $this->sourceTargetKind,
'source_target_identifier' => $this->sourceTargetIdentifier,
'detector_key' => $this->detectorKey,
'control_key' => $this->controlKey,
'package_run_id' => $this->packageRunId,
];
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
private static function stringOrDefault(mixed $value, string $default): string
{
if (! is_string($value) || trim($value) === '') {
return $default;
}
return trim($value);
}
private static function nullableString(mixed $value): ?string
{
if (! is_string($value)) {
return null;
}
$value = trim($value);
return $value === '' ? null : $value;
}
private static function nullableInt(mixed $value): ?int
{
if ($value === null || $value === '') {
return null;
}
return is_numeric($value) ? (int) $value : null;
}
}