$payload Content payload — shape depends on appliesTo. */ public function __construct( public readonly string $key, public readonly string $title, public readonly string $description, public readonly string $appliesTo, public readonly ?string $sector = null, public readonly ?string $icon = null, public readonly ?string $author = null, public readonly ?string $version = null, public readonly ?string $license = null, public readonly array $payload = [], ) {} /** * Construct from the array shape produced by Symfony YAML parsing. * * @param array $data Decoded YAML. */ public static function fromArray(array $data): self { $appliesTo = (string) ($data['appliesTo'] ?? ''); $payload = (array) ($data[$appliesTo] ?? []); return new self( key: (string) ($data['key'] ?? ''), title: (string) ($data['title'] ?? ''), description: (string) ($data['description'] ?? ''), appliesTo: $appliesTo, sector: isset($data['sector']) ? (string) $data['sector'] : null, icon: isset($data['icon']) ? (string) $data['icon'] : null, author: isset($data['author']) ? (string) $data['author'] : null, version: isset($data['version']) ? (string) $data['version'] : null, license: isset($data['license']) ? (string) $data['license'] : null, payload: $payload, ); } /** * True when this template carries a non-empty payload. */ public function isUsable(): bool { return $this->key !== '' && $this->appliesTo !== '' && $this->payload !== []; } }