Skip to content

Commit 281d55a

Browse files
committed
[Feature] StimulusBundle Form Extension
1 parent dec3eb3 commit 281d55a

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Symfony package.
7+
*
8+
* (c) Fabien Potencier <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace App\Form\Extension;
15+
16+
use Symfony\Component\Form\AbstractTypeExtension;
17+
use Symfony\Component\Form\Extension\Core\Type\FormType;
18+
use Symfony\Component\Form\FormInterface;
19+
use Symfony\Component\Form\FormView;
20+
use Symfony\Component\OptionsResolver\OptionsResolver;
21+
use Symfony\UX\StimulusBundle\Dto\StimulusAttributes;
22+
use Twig\Environment;
23+
use Twig\Loader\ArrayLoader;
24+
25+
class FormTypeExtension extends AbstractTypeExtension
26+
{
27+
private StimulusAttributes $stimulusAttributes;
28+
29+
public static function getExtendedTypes(): iterable
30+
{
31+
return [FormType::class];
32+
}
33+
34+
public function buildView(FormView $view, FormInterface $form, array $options): void
35+
{
36+
if (
37+
null === $options['stimulus_controller']
38+
&& null === $options['stimulus_target']
39+
&& null === $options['stimulus_action']
40+
) {
41+
return;
42+
}
43+
44+
$this->stimulusAttributes = new StimulusAttributes(new Environment(new ArrayLoader()));
45+
46+
if (true === \array_key_exists('stimulus_controller', $options)) {
47+
$this->handleController($options['stimulus_controller']);
48+
}
49+
50+
if (true === \array_key_exists('stimulus_target', $options)) {
51+
$this->handleTarget($options['stimulus_target']);
52+
}
53+
54+
if (true === \array_key_exists('stimulus_action', $options)) {
55+
$this->handleAction($options['stimulus_action']);
56+
}
57+
58+
$attributes = \array_merge($view->vars['attr'], $this->stimulusAttributes->toArray());
59+
60+
$view->vars['attr'] = $attributes;
61+
}
62+
63+
private function handleController(string|array $controllers): void
64+
{
65+
if (\is_string($controllers)) {
66+
$controllers = [$controllers];
67+
}
68+
69+
foreach ($controllers as $controllerName => $controller) {
70+
if (\is_string($controller)) { // 'stimulus_controller' => ['controllerName1', 'controllerName2']
71+
$this->stimulusAttributes->addController($controller);
72+
} elseif (\is_array($controller)) { // 'stimulus_controller' => ['controllerName' => ['values' => ['key' => 'value'], 'classes' => ['key' => 'value'], 'targets' => ['otherControllerName' => '.targetName']]]
73+
$this->stimulusAttributes->addController((string) $controllerName, $controller['values'] ?? [], $controller['classes'] ?? [], $controller['outlets'] ?? []);
74+
}
75+
}
76+
}
77+
78+
private function handleTarget(array $targets): void
79+
{
80+
foreach ($targets as $controllerName => $target) {
81+
$this->stimulusAttributes->addTarget($controllerName, \is_array($target) ? \implode(' ', $target) : $target);
82+
}
83+
}
84+
85+
private function handleAction(string|array $actions): void
86+
{
87+
// 'stimulus_action' => 'controllerName#actionName'
88+
// 'stimulus_action' => 'eventName->controllerName#actionName'
89+
if (\is_string($actions) && \str_contains($actions, '#')) {
90+
$eventName = null;
91+
92+
if (\str_contains($actions, '->')) {
93+
[$eventName, $rest] = \explode('->', $actions, 2);
94+
} else {
95+
$rest = $actions;
96+
}
97+
98+
[$controllerName, $actionName] = \explode('#', $rest, 2);
99+
100+
$this->stimulusAttributes->addAction($controllerName, $actionName, $eventName);
101+
102+
return;
103+
}
104+
105+
foreach ($actions as $controllerName => $action) {
106+
if (\is_string($action)) { // 'stimulus_action' => ['controllerName' => 'actionName']
107+
$this->stimulusAttributes->addAction($controllerName, $action);
108+
} elseif (\is_array($action)) {
109+
foreach ($action as $eventName => $actionName) {
110+
if (\is_string($actionName)) { // 'stimulus_action' => ['controllerName' => ['eventName' => 'actionName']]
111+
$this->stimulusAttributes->addAction($controllerName, $actionName, $eventName);
112+
} elseif (\is_array($actionName)) { // 'stimulus_action' => ['controllerName' => ['eventName' => ['actionName' => ['key' => 'value']]]]
113+
foreach ($actionName as $index => $params) {
114+
$this->stimulusAttributes->addAction($controllerName, $index, $eventName, $params);
115+
}
116+
}
117+
}
118+
}
119+
}
120+
}
121+
122+
public function configureOptions(OptionsResolver $resolver): void
123+
{
124+
parent::configureOptions($resolver);
125+
126+
$resolver->setDefaults([
127+
'stimulus_action' => null,
128+
'stimulus_controller' => null,
129+
'stimulus_target' => null,
130+
]);
131+
132+
$resolver->setAllowedTypes('stimulus_action', ['string', 'array', 'null']);
133+
$resolver->setAllowedTypes('stimulus_controller', ['string', 'array', 'null']);
134+
$resolver->setAllowedTypes('stimulus_target', ['string', 'array', 'null']);
135+
}
136+
}

0 commit comments

Comments
 (0)