httpFactoryResolver = $httpFactoryResolver ?? MessageFactoryResolver::create(); } public static function create(?FactoryResolverInterface $httpFactoryResolver = null): self { return new self($httpFactoryResolver); } public function resolve(string $endpoint, string $signal): UriInterface { $components = self::parseEndpoint($endpoint); return self::addPort( self::addUserInfo( $this->createDefaultUri($components, $signal), $components ), $components ); } public function resolveToString(string $endpoint, string $signal): string { return (string) $this->resolve($endpoint, $signal); } private function createUri(): UriInterface { return $this->httpFactoryResolver->resolveUriFactory() ->createUri(); } private function createDefaultUri(array $components, string $signal): UriInterface { if (isset($components[self::SCHEME_ATTRIBUTE])) { self::validateScheme($components[self::SCHEME_ATTRIBUTE]); } return $this->createUri() ->withScheme($components[self::SCHEME_ATTRIBUTE] ?? self::DEFAULT_SCHEME) ->withPath(self::resolvePath($components[self::PATH_ATTRIBUTE] ?? self::ROOT_PATH, $signal)) ->withHost($components[self::HOST_ATTRIBUTE]); } private static function validateScheme(string $protocol): void { if (!in_array($protocol, HttpEndpointResolverInterface::VALID_SCHEMES, true)) { throw new InvalidArgumentException(sprintf( 'Expected protocol to be http or https, given: "%s"', $protocol )); } } private static function validateSignal(string $signal): void { if (!in_array($signal, Signals::SIGNALS)) { throw new InvalidArgumentException(sprintf( 'Signal must be one of "%s". Given "%s"', implode(', ', Signals::SIGNALS), $signal )); } } private static function parseEndpoint(string $endpoint): array { $result = parse_url($endpoint); if (!is_array($result) || !isset($result[self::HOST_ATTRIBUTE])) { throw new InvalidArgumentException(sprintf( 'Failed to parse endpoint "%s"', $endpoint )); } return $result; } private static function addUserInfo(UriInterface $uri, array $components): UriInterface { if (isset($components[self::USER_ATTRIBUTE])) { $uri = $uri->withUserInfo( $components[self::USER_ATTRIBUTE], $components[self::PASS_ATTRIBUTE] ?? null ); } return $uri; } private static function addPort(UriInterface $uri, array $components): UriInterface { if (isset($components[self::PORT_ATTRIBUTE])) { $uri = $uri->withPort( $components[self::PORT_ATTRIBUTE] ); } return $uri; } private static function resolvePath(string $path, string $signal): string { self::validateSignal($signal); return str_replace('//', '/', sprintf('%s/%s', $path, self::getDefaultPath($signal))); } private static function getDefaultPath(string $signal): string { return HttpEndpointResolverInterface::DEFAULT_PATHS[$signal]; } }