Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -576,15 +576,21 @@ private function data_wp_bind_processor( WP_Interactivity_API_Directives_Process
$attribute_value = $p->get_attribute( $attribute_name );
$result = $this->evaluate( $attribute_value, end( $namespace_stack ), end( $context_stack ) );

if ( null !== $result && ( false !== $result || '-' === $bound_attribute[4] ) ) {
if ( null !== $result && (
false !== $result ||
( strlen( $bound_attribute ) > 5 && '-' === $bound_attribute[4] )
) ) {
/*
* If the result of the evaluation is a boolean and the attribute is
* `aria-` or `data-, convert it to a string "true" or "false". It
* follows the exact same logic as Preact because it needs to
* replicate what Preact will later do in the client:
* https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L131C24-L136
*/
if ( is_bool( $result ) && '-' === $bound_attribute[4] ) {
if (
is_bool( $result ) &&
( strlen( $bound_attribute ) > 5 && '-' === $bound_attribute[4] )
) {
$result = $result ? 'true' : 'false';
}
$p->set_attribute( $bound_attribute, $result );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public function set_up() {
'null' => null,
'trueString' => 'true',
'falseString' => 'false',
'trueValue' => true,
'falseValue' => false,
)
);
}
Expand Down Expand Up @@ -60,7 +62,7 @@ private function process_directives( $html ) {
public function test_wp_bind_sets_attribute() {
$html = '<div data-wp-bind--id="myPlugin::state.id">Text</div>';
list($p) = $this->process_directives( $html );
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
$this->assertSame( 'some-id', $p->get_attribute( 'id' ) );
}

/**
Expand All @@ -73,7 +75,7 @@ public function test_wp_bind_sets_attribute() {
public function test_wp_bind_replaces_attribute() {
$html = '<div id="other-id" data-wp-bind--id="myPlugin::state.id">Text</div>';
list($p) = $this->process_directives( $html );
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
$this->assertSame( 'some-id', $p->get_attribute( 'id' ) );
}

/**
Expand All @@ -86,7 +88,7 @@ public function test_wp_bind_replaces_attribute() {
public function test_wp_bind_sets_number_value() {
$html = '<img data-wp-bind--width="myPlugin::state.width">';
list($p) = $this->process_directives( $html );
$this->assertEquals( '100', $p->get_attribute( 'width' ) );
$this->assertSame( '100', $p->get_attribute( 'width' ) );
}

/**
Expand All @@ -99,8 +101,8 @@ public function test_wp_bind_sets_number_value() {
public function test_wp_bind_sets_true_string() {
$html = '<div data-wp-bind--id="myPlugin::state.trueString">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'true', $p->get_attribute( 'id' ) );
$this->assertEquals( '<div id="true" data-wp-bind--id="myPlugin::state.trueString">Text</div>', $new_html );
$this->assertSame( 'true', $p->get_attribute( 'id' ) );
$this->assertSame( '<div id="true" data-wp-bind--id="myPlugin::state.trueString">Text</div>', $new_html );
}

/**
Expand All @@ -113,8 +115,8 @@ public function test_wp_bind_sets_true_string() {
public function test_wp_bind_sets_false_string() {
$html = '<div data-wp-bind--id="myPlugin::state.falseString">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'false', $p->get_attribute( 'id' ) );
$this->assertEquals( '<div id="false" data-wp-bind--id="myPlugin::state.falseString">Text</div>', $new_html );
$this->assertSame( 'false', $p->get_attribute( 'id' ) );
$this->assertSame( '<div id="false" data-wp-bind--id="myPlugin::state.falseString">Text</div>', $new_html );
}

/**
Expand All @@ -127,7 +129,7 @@ public function test_wp_bind_sets_false_string() {
public function test_wp_bind_ignores_empty_bound_attribute() {
$html = '<div data-wp-bind="myPlugin::state.id">Text</div>';
$new_html = $this->interactivity->process_directives( $html );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );
}

/**
Expand All @@ -141,7 +143,7 @@ public function test_wp_bind_ignores_empty_bound_attribute() {
public function test_wp_bind_doesnt_do_anything_on_non_existent_references() {
$html = '<div data-wp-bind--id="myPlugin::state.nonExistengKey">Text</div>';
$new_html = $this->interactivity->process_directives( $html );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );
}

/**
Expand All @@ -154,7 +156,7 @@ public function test_wp_bind_doesnt_do_anything_on_non_existent_references() {
public function test_wp_bind_ignores_empty_value() {
$html = '<div data-wp-bind--id="">Text</div>';
$new_html = $this->interactivity->process_directives( $html );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );
}

/**
Expand All @@ -167,7 +169,7 @@ public function test_wp_bind_ignores_empty_value() {
public function test_wp_bind_ignores_without_value() {
$html = '<div data-wp-bind--id>Text</div>';
$new_html = $this->interactivity->process_directives( $html );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );
}

/**
Expand All @@ -181,7 +183,7 @@ public function test_wp_bind_ignores_without_value() {
public function test_wp_bind_works_with_multiple_same_directives() {
$html = '<div data-wp-bind--id="myPlugin::state.id" data-wp-bind--id="myPlugin::state.id">Text</div>';
list($p) = $this->process_directives( $html );
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
$this->assertSame( 'some-id', $p->get_attribute( 'id' ) );
}

/**
Expand All @@ -195,8 +197,8 @@ public function test_wp_bind_works_with_multiple_same_directives() {
public function test_wp_bind_works_with_multiple_different_directives() {
$html = '<img data-wp-bind--id="myPlugin::state.id" data-wp-bind--width="myPlugin::state.width">';
list($p) = $this->process_directives( $html );
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
$this->assertEquals( '100', $p->get_attribute( 'width' ) );
$this->assertSame( 'some-id', $p->get_attribute( 'id' ) );
$this->assertSame( '100', $p->get_attribute( 'width' ) );
}

/**
Expand All @@ -210,7 +212,7 @@ public function test_wp_bind_adds_boolean_attribute_if_true() {
$html = '<div data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertTrue( $p->get_attribute( 'hidden' ) );
$this->assertEquals( '<div hidden data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( '<div hidden data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
}

/**
Expand All @@ -225,7 +227,7 @@ public function test_wp_bind_replaces_existing_attribute_if_true() {
$html = '<div hidden="true" data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertTrue( $p->get_attribute( 'hidden' ) );
$this->assertEquals( '<div hidden data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( '<div hidden data-wp-bind--hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
}

/**
Expand All @@ -240,12 +242,12 @@ public function test_wp_bind_doesnt_add_boolean_attribute_if_false_or_null() {
$html = '<div data-wp-bind--hidden="myPlugin::state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertNull( $p->get_attribute( 'hidden' ) );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );

$html = '<div data-wp-bind--hidden="myPlugin::state.null">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertNull( $p->get_attribute( 'hidden' ) );
$this->assertEquals( $html, $new_html );
$this->assertSame( $html, $new_html );
}

/**
Expand Down Expand Up @@ -277,13 +279,13 @@ public function test_wp_bind_removes_boolean_attribute_if_false_or_null() {
public function test_wp_bind_adds_value_if_true_in_aria_or_data_attributes() {
$html = '<div data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'true', $p->get_attribute( 'aria-hidden' ) );
$this->assertEquals( '<div aria-hidden="true" data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( 'true', $p->get_attribute( 'aria-hidden' ) );
$this->assertSame( '<div aria-hidden="true" data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>', $new_html );

$html = '<div data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'true', $p->get_attribute( 'data-is-closed' ) );
$this->assertEquals( '<div data-is-closed="true" data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( 'true', $p->get_attribute( 'data-is-closed' ) );
$this->assertSame( '<div data-is-closed="true" data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>', $new_html );
}

/**
Expand All @@ -297,15 +299,15 @@ public function test_wp_bind_adds_value_if_true_in_aria_or_data_attributes() {
public function test_wp_bind_replaces_value_if_true_in_aria_or_data_attributes() {
$html = '<div aria-hidden="false" data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'true', $p->get_attribute( 'aria-hidden' ) );
$this->assertEquals( '<div aria-hidden="true" data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( 'true', $p->get_attribute( 'aria-hidden' ) );
$this->assertSame( '<div aria-hidden="true" data-wp-bind--aria-hidden="myPlugin::!state.isOpen">Text</div>', $new_html );

$html = '<div data-is-closed="false" data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>';
$new_html = $this->interactivity->process_directives( $html );
$p = new WP_HTML_Tag_Processor( $new_html );
$p->next_tag();
$this->assertEquals( 'true', $p->get_attribute( 'data-is-closed' ) );
$this->assertEquals( '<div data-is-closed="true" data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>', $new_html );
$this->assertSame( 'true', $p->get_attribute( 'data-is-closed' ) );
$this->assertSame( '<div data-is-closed="true" data-wp-bind--data-is-closed="myPlugin::!state.isOpen">Text</div>', $new_html );
}

/**
Expand All @@ -319,13 +321,13 @@ public function test_wp_bind_replaces_value_if_true_in_aria_or_data_attributes()
public function test_wp_bind_adds_value_if_false_in_aria_or_data_attributes() {
$html = '<div data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'false', $p->get_attribute( 'aria-hidden' ) );
$this->assertEquals( '<div aria-hidden="false" data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>', $new_html );
$this->assertSame( 'false', $p->get_attribute( 'aria-hidden' ) );
$this->assertSame( '<div aria-hidden="false" data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>', $new_html );

$html = '<div data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'false', $p->get_attribute( 'data-is-closed' ) );
$this->assertEquals( '<div data-is-closed="false" data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>', $new_html );
$this->assertSame( 'false', $p->get_attribute( 'data-is-closed' ) );
$this->assertSame( '<div data-is-closed="false" data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>', $new_html );
}

/**
Expand All @@ -339,13 +341,13 @@ public function test_wp_bind_adds_value_if_false_in_aria_or_data_attributes() {
public function test_wp_bind_replaces_value_if_false_in_aria_or_data_attributes() {
$html = '<div aria-hidden="true" data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'false', $p->get_attribute( 'aria-hidden' ) );
$this->assertEquals( '<div aria-hidden="false" data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>', $new_html );
$this->assertSame( 'false', $p->get_attribute( 'aria-hidden' ) );
$this->assertSame( '<div aria-hidden="false" data-wp-bind--aria-hidden="myPlugin::state.isOpen">Text</div>', $new_html );

$html = '<div data-is-closed="true" data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>';
list($p, $new_html) = $this->process_directives( $html );
$this->assertEquals( 'false', $p->get_attribute( 'data-is-closed' ) );
$this->assertEquals( '<div data-is-closed="false" data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>', $new_html );
$this->assertSame( 'false', $p->get_attribute( 'data-is-closed' ) );
$this->assertSame( '<div data-is-closed="false" data-wp-bind--data-is-closed="myPlugin::state.isOpen">Text</div>', $new_html );
}

/**
Expand Down Expand Up @@ -375,8 +377,21 @@ public function test_wp_bind_removes_value_if_null_in_aria_or_data_attributes()
public function test_wp_bind_handles_nested_bindings() {
$html = '<div data-wp-bind--id="myPlugin::state.id"><img data-wp-bind--width="myPlugin::state.width"></div>';
list($p) = $this->process_directives( $html );
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
$this->assertSame( 'some-id', $p->get_attribute( 'id' ) );
$p->next_tag();
$this->assertEquals( '100', $p->get_attribute( 'width' ) );
$this->assertSame( '100', $p->get_attribute( 'width' ) );
}

/**
* Tests handling bindings to boolean values.
*
* @ticket 60758
*
* @covers ::process_directives
*/
public function test_wp_bind_handles_true_value() {
$html = '<div data-wp-bind--id="myPlugin::state.trueValue"></div>';
list($p) = $this->process_directives( $html );
$this->assertSame( true, $p->get_attribute( 'id' ) );
}
}