Lines
100.00%
36 / 36
Methods
100.00%
5 / 5
Classes
100.00%
1 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| process | 100.00% | 9 / 9 | 100.00% | 1 / 1 | 8 | ||
| bindStoreArguments | 100.00% | 7 / 7 | 100.00% | 1 / 1 | 5 | ||
| storeReferenceFor | 100.00% | 15 / 15 | 100.00% | 1 / 1 | 6 | ||
| resolvePeerAppId | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 2 | ||
| isWritable | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 2 | ||
| 23 | final readonly class StoreAttributesPass implements CompilerPassInterface | |
| 24 | { | |
| 25 | public function process(ContainerBuilder $container): void | |
| 26 | { | |
| 27 | foreach ($container->getDefinitions() as $definition) { | |
| 28 | $class = $definition->getClass(); | |
| 29 | ||
| 30 | if ( | |
| 31 | $class === null | |
| 32 | || !$definition->isAutowired() | |
| 33 | || $definition->isAbstract() | |
| 34 | || $definition->isSynthetic() | |
| 35 | || $definition->getFactory() !== null | |
| 36 | || !class_exists($class) | |
| 37 | ) { | |
| 38 | continue; | |
| 39 | } | |
| 40 | ||
| 41 | $this->bindStoreArguments($container, $definition, $class); | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | /** @param class-string $class */ | |
| 46 | private function bindStoreArguments(ContainerBuilder $container, Definition $definition, string $class): void | |
| 47 | { | |
| 48 | $parameters = new ReflectionClass($class)->getConstructor()?->getParameters() ?? []; | |
| 49 | $arguments = $definition->getArguments(); | |
| 50 | ||
| 51 | foreach ($parameters as $parameter) { | |
| 52 | // Whatever services.php or stewart.yaml set explicitly still wins. | |
| 53 | if (\array_key_exists('$' . $parameter->getName(), $arguments) || \array_key_exists($parameter->getPosition(), $arguments)) { | |
| 54 | continue; | |
| 55 | } | |
| 56 | ||
| 57 | $store = $this->storeReferenceFor($container, $class, $parameter); | |
| 58 | ||
| 59 | if ($store !== null) { | |
| 60 | $definition->setArgument('$' . $parameter->getName(), $store); | |
| 61 | } | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | private function storeReferenceFor(ContainerBuilder $container, string $class, ReflectionParameter $parameter): ?Reference | |
| 66 | { | |
| 67 | $writable = $this->isWritable($parameter); | |
| 68 | ||
| 69 | if ($parameter->getAttributes(GlobalStore::class) !== []) { | |
| 70 | return new Reference($writable ? AppContainerBuilder::GLOBAL_STORE : AppContainerBuilder::READ_ONLY_GLOBAL_STORE); | |
| 71 | } | |
| 72 | ||
| 73 | $peer = ($parameter->getAttributes(PeerStore::class)[0] ?? null)?->newInstance(); | |
| 74 | ||
| 75 | if ($peer === null) { | |
| 76 | return null; | |
| 77 | } | |
| 78 | ||
| 79 | if ($writable) { | |
| 80 | throw ContainerException::createForReason(ContainerError::PeerStoreWritable, class: $class, parameter: $parameter->getName()); | |
| 81 | } | |
| 82 | ||
| 83 | $peerAppId = $this->resolvePeerAppId($class, $parameter, $peer); | |
| 84 | $id = AppContainerBuilder::buildPeerStoreServiceId($peerAppId); | |
| 85 | ||
| 86 | if (!$container->hasDefinition($id)) { | |
| 87 | $container->setDefinition($id, new Definition(ReadableStore::class) | |
| 88 | ->setFactory([new Reference(AppContainerBuilder::STORES), 'openPeerStoreForReading']) | |
| 89 | ->setArguments([$peerAppId])); | |
| 90 | } | |
| 91 | ||
| 92 | return new Reference($id); | |
| 93 | } | |
| 94 | ||
| 95 | /** @throws ContainerException */ | |
| 96 | private function resolvePeerAppId(string $class, ReflectionParameter $parameter, PeerStore $peer): AppId | |
| 97 | { | |
| 98 | try { | |
| 99 | return new AppId($peer->appId); | |
| 100 | } catch (IdentifierException $e) { | |
| 101 | throw ContainerException::createForReason(ContainerError::PeerStoreAppIdInvalid, $e, class: $class, parameter: $parameter->getName()); | |
| 102 | } | |
| 103 | } | |
| 104 | ||
| 105 | private function isWritable(ReflectionParameter $parameter): bool | |
| 106 | { | |
| 107 | $type = $parameter->getType(); | |
| 108 | ||
| 109 | return $type instanceof ReflectionNamedType && $type->getName() === Store::class; | |
| 110 | } | |
| 111 | } |