diff --git a/phpunit/directives/attributes/wp-each.php b/phpunit/directives/attributes/wp-each.php new file mode 100644 index 00000000..8ba2a84a --- /dev/null +++ b/phpunit/directives/attributes/wp-each.php @@ -0,0 +1,119 @@ + function( $tags, $context ) { + if ( $tags->is_tag_closer() ) { + return; + } + + $value = $tags->get_attribute( 'data-wp-text' ); + if ( null === $value ) { + return; + } + + $text = evaluate( $value, $context->get_context() ); + $tags->set_inner_html( $text ); + $tags->get_updated_html(); // FIXME: We shouldn't need to do this here. + }, + ); + + $context = new WP_Directive_Context( + array( + 'data' => array( + array( + 'id' => 123, + 'label' => 'foo', + ), + array( + 'id' => 456, + 'label' => 'bar', + ), + array( + 'id' => 789, + 'label' => 'foobar', + ), + ), + ) + ); + + $markup = << + + + + + + + + + + + + + +EOF; + $tags = new WP_Directive_Processor( $markup ); + $tags->next_tag(); // table + $tags->next_tag(); // tbody + + process_wp_each( $tags, $context, $directives ); + + $updated_markup = << + + + 123 + + foo + + + + + + + + + 456 + + bar + + + + + + + + + 789 + + foobar + + + + + + + + +EOF; + + $this->assertSame( $updated_markup, $tags->get_updated_html() ); + } +} diff --git a/src/directives/attributes/wp-each.php b/src/directives/attributes/wp-each.php new file mode 100644 index 00000000..a65610bf --- /dev/null +++ b/src/directives/attributes/wp-each.php @@ -0,0 +1,39 @@ +is_tag_closer() ) { + return; + } + + $prefixed_attributes = $tags->get_attribute_names_with_prefix( 'data-wp-each:' ); + if ( 0 === count( $prefixed_attributes ) ) { + return; + } + $attribute_name = $prefixed_attributes[0]; + + list( , $iterator_name ) = explode( ':', $attribute_name ); + + $value = $tags->get_attribute( $attribute_name ); + if ( null === $value ) { + // No wp-each directive. + return; + } + + $loop_array = evaluate( $value, $context->get_context() ); + // TODO: Error handling. + + $loop_inner_html = ''; + foreach ( $loop_array as $iteration_item ) { + $context->set_context( array( 'item' => $iteration_item ) ); + + $inner_html = $tags->get_inner_html(); + $inner_tags = new WP_Directive_Processor( $inner_html ); + $inner_tags = wp_process_directives( $inner_tags, 'data-wp-', $directives, $context ); + $loop_inner_html .= $inner_tags->get_updated_html(); + $context->rewind_context(); + } + $tags->set_inner_html( $loop_inner_html ); + $tags->next_balanced_closer(); +} diff --git a/src/directives/wp-process-directives.php b/src/directives/wp-process-directives.php index c8746e8e..3f7a5588 100644 --- a/src/directives/wp-process-directives.php +++ b/src/directives/wp-process-directives.php @@ -3,8 +3,10 @@ require_once __DIR__ . '/class-wp-directive-context.php'; require_once __DIR__ . '/class-wp-directive-processor.php'; -function wp_process_directives( $tags, $prefix, $directives ) { - $context = new WP_Directive_Context; +function wp_process_directives( $tags, $prefix, $directives, $context = null ) { + if ( ! $context ) { + $context = new WP_Directive_Context; + } $tag_stack = array(); while ( $tags->next_tag( array( 'tag_closers' => 'visit' ) ) ) { @@ -50,7 +52,7 @@ function wp_process_directives( $tags, $prefix, $directives ) { } foreach ( $attributes as $attribute ) { - call_user_func( $directives[ $attribute ], $tags, $context ); + call_user_func( $directives[ $attribute ], $tags, $context, $directives ); } } diff --git a/wp-directives.php b/wp-directives.php index d54a17ee..04bc3921 100644 --- a/wp-directives.php +++ b/wp-directives.php @@ -44,6 +44,7 @@ function () { require_once __DIR__ . '/src/directives/attributes/wp-bind.php'; require_once __DIR__ . '/src/directives/attributes/wp-context.php'; require_once __DIR__ . '/src/directives/attributes/wp-class.php'; +require_once __DIR__ . '/src/directives/attributes/wp-each.php'; require_once __DIR__ . '/src/directives/attributes/wp-html.php'; require_once __DIR__ . '/src/directives/attributes/wp-style.php'; require_once __DIR__ . '/src/directives/attributes/wp-text.php'; @@ -218,6 +219,7 @@ function process_directives_in_block( $block_content ) { 'data-wp-context' => 'process_wp_context', 'data-wp-bind' => 'process_wp_bind', 'data-wp-class' => 'process_wp_class', + 'data-wp-each' => 'process_wp_each', 'data-wp-html' => 'process_wp_html', 'data-wp-style' => 'process_wp_style', 'data-wp-text' => 'process_wp_text',