From 14b675c4263a8a043a5f97ed25c97191c73071b3 Mon Sep 17 00:00:00 2001 From: Arthur Taylor Date: Wed, 2 Jul 2025 13:47:50 +0200 Subject: [PATCH] Add support for v-else-if attributes php-vuejs-templating already supports `v-if` and `v-else` attributes. Add support for `v-else-if` to complete the conditional node support. Bug: T398318 --- src/Component.php | 55 ++++++++++++++++++++++++++++-------- tests/php/TemplatingTest.php | 30 ++++++++++++++++++++ 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/Component.php b/src/Component.php index 795aabf..0e727bb 100644 --- a/src/Component.php +++ b/src/Component.php @@ -57,7 +57,7 @@ private function handleNode( DOMNode $node, array $data ) { if ( !$this->isRemovedFromTheDom( $node ) ) { if ( !$this->handleComponent( $node, $data ) ) { $this->handleAttributeBinding( $node, $data ); - $this->handleIf( $node->childNodes, $data ); + $this->handleConditionalNodes( $node->childNodes, $data ); foreach ( iterator_to_array( $node->childNodes ) as $childNode ) { $this->handleNode( $childNode, $data ); @@ -186,14 +186,52 @@ private function handleAttributeBinding( DOMElement $node, array $data ) { } } + private function handleIf( + DOMNode $node, + array $data, + bool $previousIfCondition, + array &$nodesToRemove + ): bool { + $conditionString = $node->getAttribute( 'v-if' ); + $node->removeAttribute( 'v-if' ); + $condition = $this->app->evaluateExpression( $conditionString, $data ); + + if ( !$condition ) { + $nodesToRemove[] = $node; + } + + return $condition; + } + + private function handleElseIf( + DOMNode $node, + array $data, + bool $previousIfCondition, + array &$nodesToRemove + ): bool { + $conditionString = $node->getAttribute( 'v-else-if' ); + $node->removeAttribute( 'v-else-if' ); + if ( !$previousIfCondition ) { + $condition = $this->app->evaluateExpression( $conditionString, $data ); + + if ( !$condition ) { + $nodesToRemove[] = $node; + } + return $condition; + } + $nodesToRemove[] = $node; + return $previousIfCondition; + } + /** * @param DOMNodeList $nodes * @param array $data */ - private function handleIf( DOMNodeList $nodes, array $data ) { + private function handleConditionalNodes( DOMNodeList $nodes, array $data ) { // Iteration of iterator breaks if we try to remove items while iterating, so defer node // removing until finished iterating. $nodesToRemove = []; + $previousIfCondition = false; foreach ( $nodes as $node ) { if ( $this->isTextNode( $node ) ) { continue; @@ -201,18 +239,11 @@ private function handleIf( DOMNodeList $nodes, array $data ) { /** @var DOMElement $node */ if ( $node->hasAttribute( 'v-if' ) ) { - $conditionString = $node->getAttribute( 'v-if' ); - $node->removeAttribute( 'v-if' ); - $condition = $this->app->evaluateExpression( $conditionString, $data ); - - if ( !$condition ) { - $nodesToRemove[] = $node; - } - - $previousIfCondition = $condition; + $previousIfCondition = $this->handleIf( $node, $data, $previousIfCondition, $nodesToRemove ); + } elseif ( $node->hasAttribute( 'v-else-if' ) ) { + $previousIfCondition = $this->handleElseIf( $node, $data, $previousIfCondition, $nodesToRemove ); } elseif ( $node->hasAttribute( 'v-else' ) ) { $node->removeAttribute( 'v-else' ); - if ( $previousIfCondition ) { $nodesToRemove[] = $node; } diff --git a/tests/php/TemplatingTest.php b/tests/php/TemplatingTest.php index c24699e..7b9cea0 100644 --- a/tests/php/TemplatingTest.php +++ b/tests/php/TemplatingTest.php @@ -192,6 +192,36 @@ public function testTemplateWithIfElseBlockAndNontruthfulCondition_ElseIsDisplay $this->assertSame( '

else

', $result ); } + public function testTemplateWithElseIfBlockAndTruthfulCondition_IfAndElseRemoved() { + $result = $this->createAndRender( + '

ifelse if' . + 'else

', + [ 'variable' => false, 'other_variable' => true ] + ); + + $this->assertSame( '

else if

', $result ); + } + + public function testTemplateWithElseIfBlockAndTruthfulCondition_OnlyFirstElseIfShows() { + $result = $this->createAndRender( + '

ifelse if' . + 'another elseelse

', + [ 'variable' => false, 'other_variable' => true, 'still_another' => true ] + ); + + $this->assertSame( '

else if

', $result ); + } + + public function testTemplateWithElseIfBlockAndTruthfulIfAndElseIfCondition_IfElseRemoved() { + $result = $this->createAndRender( + '

ifelse if' . + 'else

', + [ 'variable' => true, 'other_variable' => true ] + ); + + $this->assertSame( '

if

', $result ); + } + public function testTemplateWithForLoopAndEmptyArrayToIterate_NotRendered() { $result = $this->createAndRender( '

', [ 'list' => [] ] );