Fix type handling and default value for remote API transformers (#44418)

* Add default value check and parameter, change transformer behaviour around defaults and types, update and add tests

* Changelog
This commit is contained in:
Ilyas Foo 2024-02-14 21:16:39 +08:00 committed by GitHub
parent e5e641180b
commit 8ba2942099
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 18 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Fix type handling and default value for remote API transformers

View File

@ -20,13 +20,14 @@ class OptionRuleProcessor implements RuleProcessorInterface {
* @return bool The result of the operation.
*/
public function process( $rule, $stored_state ) {
$is_contains = $rule->operation && strpos( $rule->operation, 'contains' ) !== false;
$default_value = $is_contains ? array() : false;
$default = isset( $rule->default ) ? $rule->default : $default_value;
$option_value = $this->get_option_value( $rule, $default, $is_contains );
$is_contains = $rule->operation && strpos( $rule->operation, 'contains' ) !== false;
$default_value = $is_contains ? array() : false;
$is_default_set = property_exists( $rule, 'default' );
$default = $is_default_set ? $rule->default : $default_value;
$option_value = $this->get_option_value( $rule, $default, $is_contains );
if ( isset( $rule->transformers ) && is_array( $rule->transformers ) ) {
$option_value = TransformerService::apply( $option_value, $rule->transformers, $default );
$option_value = TransformerService::apply( $option_value, $rule->transformers, $is_default_set, $default );
}
return ComparisonOperation::compare(

View File

@ -36,12 +36,13 @@ class TransformerService {
*
* @param mixed $target_value a value to transform.
* @param array $transformer_configs transform configuration.
* @param bool $is_default_set flag on is default value set.
* @param string $default default value.
*
* @throws InvalidArgumentException Throws when one of the requried arguments is missing.
* @return mixed|null
*/
public static function apply( $target_value, array $transformer_configs, $default ) {
public static function apply( $target_value, array $transformer_configs, $is_default_set, $default ) {
foreach ( $transformer_configs as $transformer_config ) {
if ( ! isset( $transformer_config->use ) ) {
throw new InvalidArgumentException( 'Missing required config value: use' );
@ -56,13 +57,25 @@ class TransformerService {
throw new InvalidArgumentException( "Unable to find a transformer by name: {$transformer_config->use}" );
}
$transformed_value = $transformer->transform( $target_value, $transformer_config->arguments, $default );
// if the transformer returns null, then return the previously transformed value.
if ( null === $transformed_value ) {
return $target_value;
$target_value = $transformer->transform( $target_value, $transformer_config->arguments, $is_default_set ? $default : null );
// Break early when there's no more value to traverse.
if ( null === $target_value ) {
break;
}
}
if ( $is_default_set ) {
// Nulls always return the default value.
if ( null === $target_value ) {
return $default;
}
$target_value = $transformed_value;
// When type of the default value is different from the target value, return the default value
// to ensure type safety.
if ( gettype( $default ) !== gettype( $target_value ) ) {
return $default;
}
}
return $target_value;

View File

@ -34,7 +34,7 @@ class WC_Admin_Tests_RemoteInboxNotifications_TransformerService extends WC_Unit
public function test_it_throw_exception_when_transformer_config_is_missing_use() {
$this->expectException( InvalidArgumentException::class );
$this->expectExceptionMessage( 'Missing required config value: use' );
TransformerService::apply( array( 'value' ), array( new stdClass() ), null );
TransformerService::apply( array( 'value' ), array( new stdClass() ), false, null );
}
/**
@ -43,22 +43,65 @@ class WC_Admin_Tests_RemoteInboxNotifications_TransformerService extends WC_Unit
public function test_it_throws_exception_when_transformer_is_not_found() {
$this->expectExceptionMessage( 'Unable to find a transformer by name: i_do_not_exist' );
$transformer = $this->transformer_config( 'i_do_not_exist' );
TransformerService::apply( array( 'value' ), array( $transformer ), null );
TransformerService::apply( array( 'value' ), array( $transformer ), false, null );
}
/**
* Given two transformers
* When the second transformer returns null
* Then the value transformed by the first transformer should be returned.
* Then the default value should be returned.
*/
public function test_it_returns_previously_transformed_value_when_transformer_returns_null() {
public function test_it_returns_default_when_transformer_returns_null() {
$dot_notation = $this->transformer_config( 'dot_notation', array( 'path' => 'industries' ) );
$array_search = $this->transformer_config( 'array_search', array( 'value' => 'i_do_not_exist' ) );
$items = array(
'industries' => array( 'item1', 'item2' ),
);
$result = TransformerService::apply( $items, array( $dot_notation, $array_search ), null );
$this->assertEquals( $result, $items['industries'] );
$result = TransformerService::apply( $items, array( $dot_notation, $array_search ), true, 'default' );
$this->assertEquals( $result, 'default' );
}
/**
* Given two transformers
* When the second transformer returns null but no default is set
* Then the final result should returned.
*/
public function test_it_returns_null_when_transformer_returns_null() {
$dot_notation = $this->transformer_config( 'dot_notation', array( 'path' => 'industries' ) );
$array_search = $this->transformer_config( 'array_search', array( 'value' => 'i_do_not_exist' ) );
$items = array(
'industries' => array( 'item1', 'item2' ),
);
$result = TransformerService::apply( $items, array( $dot_notation, $array_search ), false, null );
$this->assertEquals( $result, null );
}
/**
* Given two transformers
* When the transformed value type is different from the default value type and default is set
* Then the default value should be returned.
*/
public function test_it_returns_default_when_transformer_returns_different_type() {
$dot_notation = $this->transformer_config( 'dot_notation', array( 'path' => 'industries' ) );
$items = array(
'industries' => array(),
);
$result = TransformerService::apply( $items, array( $dot_notation ), true, 'clothing' );
$this->assertEquals( $result, 'clothing' );
}
/**
* Given two transformers
* When the transformed value type is the same with the default value type and default is set
* Then the transformed value should be returned.
*/
public function test_it_returns_default_when_transformer_returns_same_type() {
$dot_notation = $this->transformer_config( 'dot_notation', array( 'path' => 'industries' ) );
$items = array(
'industries' => 'food_and_beverage',
);
$result = TransformerService::apply( $items, array( $dot_notation ), true, 'clothing' );
$this->assertEquals( $result, 'food_and_beverage' );
}
/**
@ -94,7 +137,7 @@ class WC_Admin_Tests_RemoteInboxNotifications_TransformerService extends WC_Unit
$array_flatten = $this->transformer_config( 'array_flatten' );
$array_search = $this->transformer_config( 'array_search', array( 'value' => 'mothra-member' ) );
$result = TransformerService::apply( $items, array( $dot_notation, $array_column, $array_flatten, $array_search ), null );
$result = TransformerService::apply( $items, array( $dot_notation, $array_column, $array_flatten, $array_search ), false, null );
// Then.
$this->assertEquals( 'mothra-member', $result );