@@ -20,20 +20,12 @@ class WP_HTML_Template {
2020 private array $ replacements = array ();
2121
2222 /**
23- * Compiled placeholder metadata.
24- *
25- * @todo Consider deriving this from $edits on-demand in get_placeholders()
26- * to eliminate redundant storage. Would require building the grouped
27- * structure at call time instead of compile time.
28- *
29- * Array of placeholder_name => array with keys:
30- * - 'offsets': array of [start, length] pairs for each occurrence
31- * - 'context': 'text' or 'attribute' (attribute takes precedence)
23+ * Whether the template has been compiled.
3224 *
3325 * @since 7.0.0
34- * @var array|null
26+ * @var bool
3527 */
36- private ? array $ compiled = null ;
28+ private bool $ is_compiled = false ;
3729
3830 /**
3931 * Unified edit operations list.
@@ -62,15 +54,43 @@ class WP_HTML_Template {
6254 /**
6355 * Returns the compiled placeholder metadata.
6456 *
65- * Triggers compilation if not already done.
57+ * Derives the grouped structure from $edits on-demand.
58+ * If a placeholder appears in both text and attribute contexts,
59+ * the attribute context takes precedence (more restrictive).
6660 *
6761 * @since 7.0.0
6862 *
6963 * @return array Associative array of placeholder_name => metadata.
7064 */
7165 public function get_placeholders (): array {
7266 $ this ->compile ();
73- return $ this ->compiled ;
67+
68+ $ result = array ();
69+
70+ foreach ( $ this ->edits as $ edit ) {
71+ if ( ! isset ( $ edit ['placeholder ' ] ) ) {
72+ continue ;
73+ }
74+
75+ $ placeholder = $ edit ['placeholder ' ];
76+ $ context = $ edit ['context ' ];
77+
78+ if ( ! isset ( $ result [ $ placeholder ] ) ) {
79+ $ result [ $ placeholder ] = array (
80+ 'offsets ' => array (),
81+ 'context ' => $ context ,
82+ );
83+ } else {
84+ // Promote text context to attribute context.
85+ if ( 'attribute ' === $ context ) {
86+ $ result [ $ placeholder ]['context ' ] = 'attribute ' ;
87+ }
88+ }
89+
90+ $ result [ $ placeholder ]['offsets ' ][] = array ( $ edit ['start ' ], $ edit ['length ' ] );
91+ }
92+
93+ return $ result ;
7494 }
7595
7696 /**
@@ -83,11 +103,11 @@ public function get_placeholders(): array {
83103 * @since 7.0.0
84104 */
85105 private function compile (): void {
86- if ( null !== $ this ->compiled ) {
106+ if ( $ this ->is_compiled ) {
87107 return ;
88108 }
89109
90- $ this ->compiled = array () ;
110+ $ this ->is_compiled = true ;
91111 $ this ->edits = array ();
92112 $ this ->placeholder_names = array ();
93113
@@ -154,15 +174,6 @@ public function get_tag_attributes(): array {
154174 break ;
155175 }
156176
157- if ( ! isset ( $ this ->compiled [ $ placeholder ] ) ) {
158- $ this ->compiled [ $ placeholder ] = array (
159- 'offsets ' => array (),
160- 'context ' => 'text ' ,
161- );
162- }
163-
164- $ this ->compiled [ $ placeholder ]['offsets ' ][] = array ( $ start , $ length );
165-
166177 // New: append placeholder edit and register name.
167178 $ this ->edits [] = array (
168179 'start ' => $ start ,
@@ -232,18 +243,6 @@ public function get_tag_attributes(): array {
232243 }
233244 }
234245
235- if ( ! isset ( $ this ->compiled [ $ placeholder ] ) ) {
236- $ this ->compiled [ $ placeholder ] = array (
237- 'offsets ' => array (),
238- 'context ' => 'attribute ' ,
239- );
240- } else {
241- // Promote text context to attribute context.
242- $ this ->compiled [ $ placeholder ]['context ' ] = 'attribute ' ;
243- }
244-
245- $ this ->compiled [ $ placeholder ]['offsets ' ][] = array ( $ match_start , $ match_length );
246-
247246 // New: append placeholder edit and register name.
248247 $ this ->edits [] = array (
249248 'start ' => $ match_start ,
@@ -379,7 +378,7 @@ public function bind( array $replacements ): static {
379378 }
380379
381380 $ new = new static ( $ this ->template_string , $ replacements );
382- $ new ->compiled = $ this ->compiled ;
381+ $ new ->is_compiled = $ this ->is_compiled ;
383382 $ new ->edits = $ this ->edits ;
384383 $ new ->placeholder_names = $ this ->placeholder_names ;
385384 return $ new ;
0 commit comments