13
13
14
14
use Symfony \Component \Mercure \HubInterface ;
15
15
use Symfony \Component \Mercure \Update ;
16
- use Symfony \Component \PropertyAccess \PropertyAccess ;
17
- use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
18
16
use Symfony \UX \Turbo \Attribute \Broadcast ;
19
17
use Symfony \UX \Turbo \Broadcaster \BroadcasterInterface ;
20
- use Twig \Environment ;
21
18
22
19
/**
23
20
* Broadcasts updates rendered using Twig with Mercure.
27
24
* * id (string[]) The (potentially composite) identifier of the broadcasted entity
28
25
* * transports (string[]) The name of the transports to broadcast to
29
26
* * topics (string[]) The topics to use; the default topic is derived from the FQCN of the entity and from its id
30
- * * template (string) The Twig template to render when a new object is created, updated or removed
27
+ * * rendered_action (string) The turbo-stream action rendered as HTML
31
28
* * private (bool) Marks Mercure updates as private
32
29
* * sse_id (string) ID field of the SSE
33
30
* * sse_type (string) type field of the SSE
@@ -45,58 +42,38 @@ final class Broadcaster implements BroadcasterInterface
45
42
public const TOPIC_PATTERN = 'https://symfony.com/ux-turbo/%s/%s ' ;
46
43
47
44
private $ name ;
48
- private $ twig ;
49
45
private $ hub ;
50
- private $ propertyAccessor ;
51
- private $ templatePrefixes ;
52
46
53
- private const OPTIONS = [
54
- // Generic options
55
- 'id ' ,
56
- 'transports ' ,
57
- // Twig options
58
- 'template ' ,
59
- // Mercure options
60
- 'topics ' ,
61
- 'private ' ,
62
- 'sse_id ' ,
63
- 'sse_type ' ,
64
- 'sse_retry ' ,
65
- ];
66
-
67
- /**
68
- * @param array<string, string> $templatePrefixes
69
- */
70
- public function __construct (string $ name , Environment $ twig , HubInterface $ hub , array $ templatePrefixes = [], PropertyAccessorInterface $ propertyAccessor = null )
47
+ public function __construct (string $ name , HubInterface $ hub )
71
48
{
72
- if (80000 > \PHP_VERSION_ID ) {
73
- throw new \LogicException ('The broadcast feature requires PHP 8.0 or greater, you must either upgrade to PHP 8 or disable it. ' );
74
- }
75
-
76
49
$ this ->name = $ name ;
77
- $ this ->twig = $ twig ;
78
50
$ this ->hub = $ hub ;
79
- $ this ->templatePrefixes = $ templatePrefixes ;
80
- $ this ->propertyAccessor = $ propertyAccessor ?? (class_exists (PropertyAccess::class) ? PropertyAccess::createPropertyAccessor () : null );
81
51
}
82
52
83
53
/**
84
54
* {@inheritdoc}
85
55
*/
86
56
public function broadcast (object $ entity , string $ action , array $ options ): void
87
57
{
88
- $ options = $ this ->normalizeOptions ($ entity , $ action , $ options );
89
-
90
- if (isset ($ options ['transports ' ]) && !\in_array ($ this ->name , $ options ['transports ' ], true )) {
58
+ if (isset ($ options ['transports ' ]) && !\in_array ($ this ->name , (array ) $ options ['transports ' ], true )) {
91
59
return ;
92
60
}
93
61
94
- // Will throw if the template or the block doesn't exist
95
- $ data = $ this ->twig ->load ($ options ['template ' ])->renderBlock ($ action , ['entity ' => $ entity , 'action ' => $ action ] + $ options );
62
+ $ entityClass = \get_class ($ entity );
63
+
64
+ if (!isset ($ options ['rendered_action ' ])) {
65
+ throw new \InvalidArgumentException (sprintf ('Cannot broadcast entity of class "%s" as option "rendered_action" is missing. ' , $ entityClass ));
66
+ }
67
+
68
+ if (!isset ($ options ['topic ' ]) && !isset ($ options ['id ' ])) {
69
+ throw new \InvalidArgumentException (sprintf ('Cannot broadcast entity of class "%s": either option "topics" or "id" is missing, or the PropertyAccess component is not installed. Try running "composer require property-access". ' , $ entityClass ));
70
+ }
71
+
72
+ $ options ['topics ' ] = (array ) ($ options ['topics ' ] ?? sprintf (self ::TOPIC_PATTERN , rawurlencode ($ entityClass ), rawurlencode (implode ('- ' , (array ) $ options ['id ' ]))));
96
73
97
74
$ update = new Update (
98
75
$ options ['topics ' ],
99
- $ data ,
76
+ $ options [ ' rendered_action ' ] ,
100
77
$ options ['private ' ] ?? false ,
101
78
$ options ['sse_id ' ] ?? null ,
102
79
$ options ['sse_type ' ] ?? null ,
@@ -105,49 +82,4 @@ public function broadcast(object $entity, string $action, array $options): void
105
82
106
83
$ this ->hub ->publish ($ update );
107
84
}
108
-
109
- /**
110
- * @param mixed[] $options
111
- *
112
- * @return mixed[]
113
- */
114
- private function normalizeOptions (object $ entity , string $ action , array $ options ): array
115
- {
116
- if (isset ($ options ['transports ' ])) {
117
- $ options ['transports ' ] = (array ) $ options ['transports ' ];
118
- }
119
-
120
- $ entityClass = \get_class ($ entity );
121
-
122
- if ($ extraKeys = array_diff (array_keys ($ options ), self ::OPTIONS )) {
123
- throw new \InvalidArgumentException (sprintf ('Unknown broadcast options "%s" on class "%s". Valid options are: "%s" ' , implode ('", " ' , $ extraKeys ), $ entityClass , implode ('", " ' , self ::OPTIONS )));
124
- }
125
-
126
- if (isset ($ options ['id ' ])) {
127
- $ options ['id ' ] = \is_array ($ options ['id ' ]) ? implode ('- ' , $ options ['id ' ]) : $ options ['id ' ];
128
- } elseif (!isset ($ options ['topics ' ])) {
129
- if (!$ this ->propertyAccessor ) {
130
- throw new \InvalidArgumentException (sprintf ('Cannot broadcast entity of class "%s": either option "topics" or "id" is missing, or the PropertyAccess component is not installed. Try running "composer require property-access". ' , $ entityClass ));
131
- }
132
-
133
- $ options ['id ' ] = $ this ->propertyAccessor ->getValue ($ entity , 'id ' );
134
- }
135
-
136
- $ options ['topics ' ] = (array ) ($ options ['topics ' ] ?? sprintf (self ::TOPIC_PATTERN , rawurlencode ($ entityClass ), rawurlencode ($ options ['id ' ])));
137
- if (isset ($ options ['template ' ])) {
138
- return $ options ;
139
- }
140
-
141
- $ file = $ entityClass ;
142
- foreach ($ this ->templatePrefixes as $ namespace => $ prefix ) {
143
- if (0 === strpos ($ entityClass , $ namespace )) {
144
- $ file = substr_replace ($ entityClass , $ prefix , 0 , \strlen ($ namespace ));
145
- break ;
146
- }
147
- }
148
-
149
- $ options ['template ' ] = str_replace ('\\' , '/ ' , $ file ).'.stream.html.twig ' ;
150
-
151
- return $ options ;
152
- }
153
85
}
0 commit comments