Skip to content

Commit 4485581

Browse files
committed
[Twig] Store mount methods in compiler pass
1 parent 7dff0df commit 4485581

File tree

2 files changed

+62
-29
lines changed

2 files changed

+62
-29
lines changed

src/TwigComponent/src/ComponentFactory.php

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use Symfony\Component\DependencyInjection\ServiceLocator;
1616
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
1717
use Symfony\Contracts\Service\ResetInterface;
18-
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
1918
use Symfony\UX\TwigComponent\Event\PostMountEvent;
2019
use Symfony\UX\TwigComponent\Event\PreMountEvent;
2120

@@ -27,8 +26,6 @@
2726
final class ComponentFactory implements ResetInterface
2827
{
2928
private static $mountMethods = [];
30-
private static $preMountMethods = [];
31-
private static $postMountMethods = [];
3229

3330
/**
3431
* @param array<string, array> $config
@@ -151,23 +148,15 @@ private function mount(object $component, array &$data): void
151148

152149
return;
153150
}
154-
155-
if (null === (self::$mountMethods[$component::class] ?? null)) {
156-
try {
157-
$mountMethod = self::$mountMethods[$component::class] = (new \ReflectionClass($component))->getMethod('mount');
158-
} catch (\ReflectionException) {
159-
self::$mountMethods[$component::class] = false;
160-
161-
return;
162-
}
163-
}
164-
165-
if (false === $mountMethod ??= self::$mountMethods[$component::class]) {
151+
152+
if (!($this->config[$component::class]['mount'] ?? false)) {
166153
return;
167154
}
168-
155+
156+
$mount = self::$mountMethods[$component::class] ??= (new \ReflectionClass($component))->getMethod('mount');
157+
169158
$parameters = [];
170-
foreach ($mountMethod->getParameters() as $refParameter) {
159+
foreach ($mount->getParameters() as $refParameter) {
171160
if (\array_key_exists($name = $refParameter->getName(), $data)) {
172161
$parameters[] = $data[$name];
173162
// remove the data element so it isn't used to set the property directly.
@@ -179,7 +168,7 @@ private function mount(object $component, array &$data): void
179168
}
180169
}
181170

182-
$mountMethod->invoke($component, ...$parameters);
171+
$mount->invoke($component, ...$parameters);
183172
}
184173

185174
private function preMount(object $component, array $data, ComponentMetadata $componentMetadata): array
@@ -188,10 +177,11 @@ private function preMount(object $component, array $data, ComponentMetadata $com
188177
$this->eventDispatcher->dispatch($event);
189178
$data = $event->getData();
190179

191-
$methods = self::$preMountMethods[$component::class] ??= AsTwigComponent::preMountMethods($component::class);
192-
foreach ($methods as $method) {
193-
if (null !== $newData = $method->invoke($component, $data)) {
194-
$data = $newData;
180+
if ($preMounts = $this->config[$component::class]['preMount'] ?? []) {
181+
foreach ($preMounts as $preMount) {
182+
if (null !== $newData = $component->$preMount($data)) {
183+
$data = $newData;
184+
}
195185
}
196186
}
197187

@@ -207,10 +197,11 @@ private function postMount(object $component, array $data, ComponentMetadata $co
207197
$this->eventDispatcher->dispatch($event);
208198
$data = $event->getData();
209199

210-
$methods = self::$postMountMethods[$component::class] ??= AsTwigComponent::postMountMethods($component::class);
211-
foreach ($methods as $method) {
212-
if (null !== $newData = $method->invoke($component, $data)) {
213-
$data = $newData;
200+
if ($postMounts = $this->config[$component::class]['postMount'] ?? []) {
201+
foreach ($postMounts as $postMount) {
202+
if (null !== $newData = $component->$postMount($data)) {
203+
$data = $newData;
204+
}
214205
}
215206
}
216207

@@ -257,7 +248,5 @@ private function throwUnknownComponentException(string $name): void
257248
public function reset(): void
258249
{
259250
self::$mountMethods = [];
260-
self::$preMountMethods = [];
261-
self::$postMountMethods = [];
262251
}
263252
}

src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
1717
use Symfony\Component\DependencyInjection\Exception\LogicException;
1818
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\UX\TwigComponent\Attribute\PostMount;
20+
use Symfony\UX\TwigComponent\Attribute\PreMount;
1921

2022
/**
2123
* @author Kevin Bond <kevinbond@gmail.com>
@@ -68,7 +70,7 @@ public function process(ContainerBuilder $container): void
6870
$tag['service_id'] = $id;
6971
$tag['class'] = $definition->getClass();
7072
$tag['template'] = $tag['template'] ?? $this->calculateTemplate($tag['key'], $defaults);
71-
$componentConfig[$tag['key']] = $tag;
73+
$componentConfig[$tag['key']] = [...$tag, ...$this->getMountMethods($tag['class'])];
7274
$componentReferences[$tag['key']] = new Reference($id);
7375
$componentNames[] = $tag['key'];
7476
$componentClassMap[$tag['class']] = $tag['key'];
@@ -109,4 +111,46 @@ private function calculateTemplate(string $componentName, ?array $defaults): str
109111

110112
return \sprintf('%s/%s.html.twig', rtrim($directory, '/'), str_replace(':', '/', $componentName));
111113
}
114+
115+
/**
116+
* @param class-string $component
117+
* @return array{preMount: string[], mount: string[], postMount: string[]}
118+
*/
119+
private function getMountMethods(string $component): array
120+
{
121+
$preMount = [];
122+
$mount = [];
123+
$postMount = [];
124+
125+
foreach ((new \ReflectionClass($component))->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
126+
foreach ($method->getAttributes(PreMount::class) as $attribute) {
127+
$preMount[$method->getName()] = $attribute->newInstance()->priority;
128+
}
129+
foreach ($method->getAttributes(PostMount::class) as $attribute) {
130+
$postMount[$method->getName()] = $attribute->newInstance()->priority;
131+
}
132+
if ('mount' === $method->getName()) {
133+
$mount['mount'] = 0;
134+
}
135+
}
136+
137+
if ($preMount) {
138+
arsort($preMount);
139+
$preMount = array_keys($preMount);
140+
}
141+
if ($mount) {
142+
arsort($mount);
143+
$mount = array_keys($mount);
144+
}
145+
if ($postMount) {
146+
arsort($postMount);
147+
$postMount = array_keys($postMount);
148+
}
149+
150+
return [
151+
'preMount' => $preMount,
152+
'mount' => $mount,
153+
'postMount' => $postMount,
154+
];
155+
}
112156
}

0 commit comments

Comments
 (0)