config = $config; } public static function createDefault(): Configuration { return new Configuration([ "publish.overwrite_ids" => false, "publish.reject_duplicates" => false, "server.address" => "127.0.0.1:9000", "server.websockets" => false, "server.enable_api" => true, "server.limits.max_concurrent" => 100, "server.limits.max_request_body" => 102400, "server.cors.allow_origin" => "*", "server.cors.csp" => "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'", "subscribe.allow_anonymous" => true, "security.jwt_secret" => "!ChangeThisMercureHubJWTSecretKey!", ]); } public static function fromFile(string $file): Configuration { $config = new Configuration(); $file = realpath($file); if (!file_exists($file)) { throw new \Exception("Configuration file not found"); } $data = file_get_contents($file); $yaml = Yaml::parse($data); $unwrap = null; // mute IDE complains about $unwrap not defined $unwrap = function (array $array, Configuration $target, array $path=[]) use (&$unwrap) { foreach ($array as $key=>$value) { if (is_array($value)) { $unwrap($value, $target, [ ...$path, $key ]); } else { $key = join(".", [ ...$path, $key ]); $target->config[$key] = $value; } } }; $unwrap($yaml, $config); return $config; } /** * Retrieve a key from the configuration. If the key ends with a dot, all values * with keys starting with the requested key are returned. If the key is a single * dot, all keys are matched and all values returned. * * @param string $key * @param mixed $default Default value * @return mixed */ public function get(string $key, $default = null): mixed { if ($key === '.') return $this->config; if (str_ends_with($key, ".")) return array_filter($this->config, fn($k)=>str_starts_with($k,$key), ARRAY_FILTER_USE_KEY); return $this->config[$key] ?? $default; } public function setPublicUrl(string $publicUrl): self { $this->config['server.public_url'] = $publicUrl; return $this; } public function getPublicUrl(): ?string { return $this->config['server.public_url']??null; } public function setJwtSecret(string $secret): self { $this->config['security.jwt_secret'] = $secret; return $this; } public function getJwtSecret(): ?string { return $this->config['security.jwt_secret']??null; } function getAllowAnonymousSubscribe():bool { return $this->config['subscribe.allow_anonymous']??false; } function setAllowAnonymousSubscribe(bool $allowAnonymousSubscribe): self { $this->config['subscribe.allow_anonymous'] = $allowAnonymousSubscribe; return $this; } public function setListenAddress(string $address): self { $this->config['server.address'] = $address; return $this; } public function getListenAddress(): ?string { return $this->config['server.address']??null; } public function setAllowOriginHeader(string $value): self { $this->config['headers.allow_origin'] = $value; return $this; } public function setContentSecurityPolicyHeader(string $value): self { $this->config['headers.csp'] = $value; return $this; } public function getEnableWebSockets(): bool { return (bool)($this->config['server.websockets']??false); } public function setEnableWebSockets(bool $enable): self { $this->config['server.websockets'] = $enable; return $this; } public function getOverwriteMessageIds(): bool { return $this->config['publish.overwrite_ids']??true; } public function getRejectDuplicateMessages(): bool { return $this->config['publish.reject_duplicates']??true; } public function getDuplicateIdHistorySize(): int { return 50; } }