@@ -128,48 +128,64 @@ public static function parseString(mixed $string, array $arguments = [], bool $s
128128 */
129129 public static function parseConditions (string $ string , array $ arguments = [], int $ offset = 0 , ?string $ pattern = null ): string
130130 {
131- preg_match ($ pattern ?? static ::CONDITION_PATTERN , $ string , $ matches , PREG_OFFSET_CAPTURE , $ offset );
132- if (!$ matches ) {
133- return $ string ;
134- }
131+ $ pattern = $ pattern ?? static ::CONDITION_PATTERN ;
135132
133+ while (preg_match ($ pattern , $ string , $ matches , PREG_OFFSET_CAPTURE , $ offset )) {
134+ $ result = static ::getConditionResult ($ matches , $ arguments );
136135
137- $ result = static ::getConditionResult ($ matches , $ arguments );
136+ $ conditionStart = (int )$ matches [0 ][1 ];
137+ $ conditionLength = strlen ($ matches [0 ][0 ]);
138+ $ insideBlockStart = $ conditionStart + $ conditionLength ;
138139
139- $ conditionStart = ( int ) $ matches [ 0 ][ 1 ] ;
140- $ conditionLength = strlen ( $ matches [ 0 ][ 0 ]) ;
141- $ insideBlockStart = $ conditionStart + $ conditionLength ;
140+ $ hasElse = false ;
141+ $ elseStart = null ;
142+ $ conditionEnd = null ;
142143
143- $ hasElse = false ;
144- $ elseCount = preg_match ('/<%\s?else\s?%>\n?/ ' , $ string , $ elseMatches , PREG_OFFSET_CAPTURE , $ offset );
145- if ($ elseCount !== false && $ elseCount === 1 && $ elseMatches ) {
146- $ hasElse = true ;
147- $ elseStart = (int ) $ elseMatches [0 ][1 ];
148- $ elseTagLength = strlen ($ elseMatches [0 ][0 ]);
149- $ elseBlock = static ::parseElseTag ($ string , $ elseStart , $ elseTagLength , $ arguments , $ offset );
150- } else if ($ elseCount > 1 ) {
151- throw new RuntimeException ("Too many <% else %> tags. " );
152- } else {
153- $ string = static ::parseNestedIfs ($ string , $ arguments , $ offset + $ conditionLength , $ insideBlockStart );
154- }
144+ $ nestedOffset = $ insideBlockStart ;
145+ $ nestedIfCount = 0 ;
146+ $ elseMatch = null ;
155147
156- preg_match ('/<%\s?endif\s?%>\n?/ ' , $ string , $ endMatches , PREG_OFFSET_CAPTURE , $ offset );
157- if (!$ endMatches ) {
158- throw new RuntimeException ("Missing <% endif %> tag. " );
159- }
148+ while (preg_match ('/<%\s?(if|else|endif)\s?.*?%>\n?/m ' , $ string , $ tagMatches , PREG_OFFSET_CAPTURE , $ nestedOffset )) {
149+ $ tag = $ tagMatches [1 ][0 ];
150+ $ tagStart = (int )$ tagMatches [0 ][1 ];
151+
152+ if ($ tag === 'if ' ) {
153+ $ nestedIfCount ++;
154+ } elseif ($ tag === 'endif ' ) {
155+ if ($ nestedIfCount === 0 ) {
156+ $ conditionEnd = $ tagStart ;
157+ break ;
158+ }
159+ $ nestedIfCount --;
160+ } elseif ($ tag === 'else ' && $ nestedIfCount === 0 ) {
161+ $ hasElse = true ;
162+ $ elseStart = $ tagStart ;
163+ $ elseMatch = $ tagMatches [0 ][0 ];
164+ }
160165
161- $ conditionEnd = $ endMatches [0 ][1 ] ;
162- $ replaceLength = $ conditionEnd - $ conditionStart + strlen ( $ endMatches [ 0 ][ 0 ]);
166+ $ nestedOffset = $ tagStart + strlen ( $ tagMatches [0 ][0 ]) ;
167+ }
163168
164- if ($ hasElse ) {
165- $ insideBlock = substr ($ string , $ insideBlockStart , $ elseStart - $ insideBlockStart );
166- $ string = substr_replace ($ string , $ result ? $ insideBlock : $ elseBlock , $ conditionStart , $ replaceLength );
167- } else {
168- $ insideBlock = substr ($ string , $ insideBlockStart , $ conditionEnd - $ insideBlockStart );
169- $ string = substr_replace ($ string , $ result ? $ insideBlock : '' , $ conditionStart , $ replaceLength );
169+ if ($ conditionEnd === null ) {
170+ throw new RuntimeException ("Missing <% endif %> tag. " );
171+ }
172+
173+ $ replaceLength = $ conditionEnd - $ conditionStart + strlen ($ tagMatches [0 ][0 ]);
174+
175+ if ($ hasElse ) {
176+ $ elseTagLength = strlen ($ elseMatch ); // Correctly calculate the length of the `<% else %>` tag
177+ $ insideBlock = substr ($ string , $ insideBlockStart , $ elseStart - $ insideBlockStart );
178+ $ elseBlock = substr ($ string , $ elseStart + $ elseTagLength , $ conditionEnd - ($ elseStart + $ elseTagLength ));
179+ $ string = substr_replace ($ string , $ result ? $ insideBlock : $ elseBlock , $ conditionStart , $ replaceLength );
180+ } else {
181+ $ insideBlock = substr ($ string , $ insideBlockStart , $ conditionEnd - $ insideBlockStart );
182+ $ string = substr_replace ($ string , $ result ? $ insideBlock : '' , $ conditionStart , $ replaceLength );
183+ }
184+
185+ $ offset = $ conditionStart ;
170186 }
171187
172- return static :: parseConditions ( $ string, $ arguments , $ conditionStart , $ pattern ) ;
188+ return $ string ;
173189 }
174190
175191 public static function removeComments (string $ string , ?string $ pattern = null ): string
@@ -541,50 +557,6 @@ protected static function getResultByOperator(mixed $left, ?string $operator, mi
541557 }
542558 }
543559
544- /**
545- * Parse the else block of the condition.
546- * @param string &$string The string to parse (by reference - will be modified in place)
547- * @param int $elseStart The position of the else tag in the string
548- * @param int $elseTagLength The length of the else tag
549- * @param array $arguments Array with the arguments (variables) from the template
550- * @param int $offset Offset to start replacing the condition from
551- * @return string The parsed else block
552- */
553- protected static function parseElseTag (string &$ string , int $ elseStart , int $ elseTagLength , array $ arguments = [], $ offset = 0 ): string
554- {
555- $ string = static ::parseNestedIfs ($ string , $ arguments , $ elseStart + $ elseTagLength , (int )$ elseStart + $ elseTagLength );
556-
557- preg_match ('/<%\s?endif\s?%>\n?/ ' , $ string , $ endMatches , PREG_OFFSET_CAPTURE , $ offset );
558- if (!$ endMatches ) {
559- throw new RuntimeException ("Missing <% endif %> tag. " );
560- }
561-
562- $ conditionEnd = $ endMatches [0 ][1 ];
563-
564- $ elseBlock = substr ($ string , $ elseStart + $ elseTagLength , $ conditionEnd - $ elseStart - $ elseTagLength );
565-
566- return $ elseBlock ;
567- }
568-
569- /**
570- * Parse nested if conditions.
571- * @param string $string The string to parse
572- * @param array $arguments Array with the arguments (variables) from the template
573- * @param int $searchOffset Offset to start searching for the condition from
574- * @param int $replaceOffset Offset to start replacing the condition from
575- * @param string $pattern Pattern to use for the condition
576- * @return string The parsed string
577- */
578- protected static function parseNestedIfs (string $ string , array $ arguments = [], int $ searchOffset = 0 , int $ replaceOffset = 0 , ?string $ pattern = null ): string
579- {
580- $ nestedIfs = preg_match_all (static ::CONDITION_PATTERN , $ string , $ nestedMatches , PREG_OFFSET_CAPTURE , $ searchOffset );
581- if ($ nestedIfs !== false && $ nestedIfs > 0 ) {
582- $ string = static ::parseConditions ($ string , $ arguments , $ replaceOffset , $ pattern );
583- }
584-
585- return $ string ;
586- }
587-
588560 /**
589561 * @param string $defaultMatch The default value match
590562 * @return mixed The default value
0 commit comments