Lines
100.00%
42 / 42
Methods
100.00%
5 / 5
Classes
100.00%
1 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| parseServicesResponse | 100.00% | 11 / 11 | 100.00% | 1 / 1 | 3 | ||
| parseDefinition | 100.00% | 9 / 9 | 100.00% | 1 / 1 | 1 | ||
| flattenFields | 100.00% | 8 / 8 | 100.00% | 1 / 1 | 3 | ||
| parseField | 100.00% | 12 / 12 | 100.00% | 1 / 1 | 1 | ||
| sortRequiredFirstThenByName | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | ||
| 10 | final readonly class ServiceCatalogParser | |
| 11 | { | |
| 12 | /** @param array<string, mixed> $raw */ | |
| 13 | public function parseServicesResponse(array $raw): ServiceCatalog | |
| 14 | { | |
| 15 | $byDomain = []; | |
| 16 | ||
| 17 | $response = RawMap::fromValue($raw); | |
| 18 | ||
| 19 | foreach ($response->listKeys() as $domain) { | |
| 20 | $services = $response->readMap($domain); | |
| 21 | $definitions = []; | |
| 22 | ||
| 23 | foreach ($services->listKeys() as $name) { | |
| 24 | $definitions[$name] = $this->parseDefinition($domain, $name, $services->readMap($name)); | |
| 25 | } | |
| 26 | ||
| 27 | ksort($definitions); | |
| 28 | $byDomain[$domain] = ServiceDefinitionCollection::fromList($definitions); | |
| 29 | } | |
| 30 | ||
| 31 | ksort($byDomain); | |
| 32 | ||
| 33 | return new ServiceCatalog($byDomain); | |
| 34 | } | |
| 35 | ||
| 36 | private function parseDefinition(string $domain, string $name, RawMap $service): ServiceDefinition | |
| 37 | { | |
| 38 | return new ServiceDefinition( | |
| 39 | domain: $domain, | |
| 40 | name: $name, | |
| 41 | title: $service->readString('name'), | |
| 42 | description: $service->readString('description'), | |
| 43 | fields: $this->sortRequiredFirstThenByName($this->flattenFields($service->readMap('fields'))), | |
| 44 | target: ServiceTargetSpec::fromRaw($service), | |
| 45 | returnsResponse: $service->hasKey('response'), | |
| 46 | ); | |
| 47 | } | |
| 48 | ||
| 49 | /** @return list<ServiceField> */ | |
| 50 | private function flattenFields(RawMap $fields): array | |
| 51 | { | |
| 52 | $flat = []; | |
| 53 | ||
| 54 | foreach ($fields->listKeys() as $name) { | |
| 55 | $field = $fields->readMap($name); | |
| 56 | ||
| 57 | if ($field->hasKey('fields')) { | |
| 58 | $flat = [...$flat, ...$this->flattenFields($field->readMap('fields'))]; | |
| 59 | ||
| 60 | continue; | |
| 61 | } | |
| 62 | ||
| 63 | $flat[] = $this->parseField($name, $field); | |
| 64 | } | |
| 65 | ||
| 66 | return $flat; | |
| 67 | } | |
| 68 | ||
| 69 | private function parseField(string $name, RawMap $field): ServiceField | |
| 70 | { | |
| 71 | $selector = new ServiceSelector($field->readMap('selector')); | |
| 72 | $configuration = $selector->configuration; | |
| 73 | ||
| 74 | return new ServiceField( | |
| 75 | name: $name, | |
| 76 | type: $selector->resolvePhpType(), | |
| 77 | required: $field->readBool('required'), | |
| 78 | label: $field->readString('name'), | |
| 79 | description: $field->readString('description'), | |
| 80 | unit: $configuration->readString('unit_of_measurement'), | |
| 81 | min: $configuration->readNumber('min'), | |
| 82 | max: $configuration->readNumber('max'), | |
| 83 | ); | |
| 84 | } | |
| 85 | ||
| 86 | /** | |
| 87 | * @param list<ServiceField> $fields | |
| 88 | * @return list<ServiceField> | |
| 89 | */ | |
| 90 | private function sortRequiredFirstThenByName(array $fields): array | |
| 91 | { | |
| 92 | usort($fields, static fn(ServiceField $a, ServiceField $b): int => [!$a->required, $a->name] <=> [!$b->required, $b->name]); | |
| 93 | ||
| 94 | return $fields; | |
| 95 | } | |
| 96 | } |