Lines
100.00%
18 / 18
Functions and Methods
100.00%
5 / 5
Classes and Traits
100.00%
1 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| MqttServerUrl | 100.00% | 18 / 18 | 100.00% | 5 / 5 | 12 | 100.00% | 1 / 1 | |||
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| parse | 100.00% | 14 / 14 | 100.00% | 1 / 1 | 8 | |||||
| revealPassword | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| toSocketUri | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| __toString | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Stewart\Runtime\Config; | |
| 6 | ||
| 7 | use SensitiveParameter; | |
| 8 | use Stewart\Runtime\Exception\ConfigurationException; | |
| 9 | use Stewart\Support\Url\UrlRedactor; | |
| 10 | use Stringable; | |
| 11 | ||
| 12 | final readonly class MqttServerUrl implements Stringable | |
| 13 | { | |
| 14 | private const string PLAIN_SCHEME = 'mqtt'; | |
| 15 | ||
| 16 | private const string TLS_SCHEME = 'mqtts'; | |
| 17 | ||
| 18 | private const int PLAIN_DEFAULT_PORT = 1883; | |
| 19 | ||
| 20 | private const int TLS_DEFAULT_PORT = 8883; | |
| 21 | ||
| 22 | private function __construct( | |
| 23 | public bool $usesTls, | |
| 24 | public string $host, | |
| 25 | public int $port, | |
| 26 | public ?string $username, | |
| 27 | #[SensitiveParameter] | |
| 28 | private ?string $password, | |
| 29 | private string $redacted, | |
| 30 | ) {} | |
| 31 | ||
| 32 | /** @throws ConfigurationException */ | |
| 33 | public static function parse(#[SensitiveParameter] string $url): self | |
| 34 | { | |
| 35 | $redacted = UrlRedactor::redactCredentials($url); | |
| 36 | $parts = parse_url($url); | |
| 37 | $scheme = \is_array($parts) ? strtolower($parts['scheme'] ?? '') : ''; | |
| 38 | ||
| 39 | if (!\is_array($parts) || !isset($parts['host']) || !\in_array($scheme, [self::PLAIN_SCHEME, self::TLS_SCHEME], true)) { | |
| 40 | throw ConfigurationException::valueInvalid($redacted, 'an MQTT server URL; use mqtt://host:port or mqtts://host:port'); | |
| 41 | } | |
| 42 | ||
| 43 | $usesTls = $scheme === self::TLS_SCHEME; | |
| 44 | ||
| 45 | return new self( | |
| 46 | usesTls: $usesTls, | |
| 47 | host: $parts['host'], | |
| 48 | port: $parts['port'] ?? ($usesTls ? self::TLS_DEFAULT_PORT : self::PLAIN_DEFAULT_PORT), | |
| 49 | username: isset($parts['user']) ? rawurldecode($parts['user']) : null, | |
| 50 | password: isset($parts['pass']) ? rawurldecode($parts['pass']) : null, | |
| 51 | redacted: $redacted, | |
| 52 | ); | |
| 53 | } | |
| 54 | ||
| 55 | public function revealPassword(): ?string | |
| 56 | { | |
| 57 | return $this->password; | |
| 58 | } | |
| 59 | ||
| 60 | public function toSocketUri(): string | |
| 61 | { | |
| 62 | return 'tcp://' . $this->host . ':' . $this->port; | |
| 63 | } | |
| 64 | ||
| 65 | public function __toString(): string | |
| 66 | { | |
| 67 | return $this->redacted; | |
| 68 | } | |
| 69 | } |