'HTTP (port 80)', 'https' => 'HTTPS (port 443, desktop)', 'ssh' => 'SSH tunnel to the host', 'demo' => 'Demo pool (no server)']; public function __construct( public string $host, public string $user = 'root', public string $password = '', public string $method = 'http', public int $port = 0, public bool $remember = false, public string $sshUser = 'root', public int $sshPort = 22, public string $sshKey = '', public string $friendlyName = '', /** @var array host uuid => the address the user reaches it at (a pool behind a VPN / NAT): Connection Addresses… */ public array $hostAddresses = [], ) { } public static function demo(): self { return new self('xcp-demo.local', \App\Xapi\FakeXapi::USER, \App\Xapi\FakeXapi::PASSWORD, 'demo', 0, true, 'root', 22, '', 'Demo pool'); } /** Another demo server: a standalone host of its own (FakeXapi builds one for any address but the demo pool's), e.g. 'xcp-demo-2.local' = xcp-ng-03. */ public static function demoServer(string $address = 'xcp-demo-2.local'): self { return new self($address, \App\Xapi\FakeXapi::USER, \App\Xapi\FakeXapi::PASSWORD, 'demo', 0, true); } public function port(): int { return $this->port > 0 ? $this->port : ($this->method === 'https' ? 443 : 80); } public function key(): string { return $this->method . '://' . strtolower($this->host) . ':' . $this->port(); } /** @return array what is saved: the password only when "remember" is ticked, and then sealed (never in clear) */ public function toArray(?Keyring $keyring = null): array { if (!$this->remember) { $this->secret = ''; } elseif ($this->password !== '' && ($sealed = $keyring?->seal($this->password)) !== null) { $this->secret = $sealed; // locked by a master password not given yet: the one sealed before is kept } return ['host' => $this->host, 'user' => $this->user, 'secret' => $this->secret, 'method' => $this->method, 'port' => $this->port, 'remember' => $this->remember, 'sshUser' => $this->sshUser, 'sshPort' => $this->sshPort, 'sshKey' => $this->sshKey, 'friendlyName' => $this->friendlyName, 'hostAddresses' => $this->hostAddresses]; } /** @param array $a */ public static function fromArray(array $a): self { // 'password': a clear one of an older version (Keyring::restore() writes it again sealed) $profile = new self((string)($a['host'] ?? ''), (string)($a['user'] ?? 'root'), (string)($a['password'] ?? ''), (string)($a['method'] ?? 'http'), (int)($a['port'] ?? 0), (bool)($a['remember'] ?? false), (string)($a['sshUser'] ?? 'root'), (int)($a['sshPort'] ?? 22), (string)($a['sshKey'] ?? ''), (string)($a['friendlyName'] ?? ''), array_map('strval', array_filter((array)($a['hostAddresses'] ?? []), fn ($v) => is_scalar($v) && trim((string)$v) !== ''))); $profile->secret = (string)($a['secret'] ?? ''); return $profile; } }