Skip to content

Commit

Permalink
fix: handle RadioField submission values when using a custom "other" …
Browse files Browse the repository at this point in the history
…choice (#421)
  • Loading branch information
justlevine authored Jun 4, 2024
1 parent e68b7c0 commit b70ef41
Show file tree
Hide file tree
Showing 11 changed files with 389 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- feat!: Implement `FormField` model and `DataLoader`, and refactor `FormFieldsConnectionResolver` to extend `AbstractConnectionResolver`.
- feat!: Refactor `FormsConnectionResolver` and `EntriesConnectionResolver` for compatibility with WPGraphQL v1.26.0 improvements.
- feat!: Narrow `FormField.choices` and `FormField.inputs` field types to their implementations.
- fix: Handle RadioField submission values when using a custom "other" choice. H/t @Gytjarek .
- dev: Use `FormFieldsDataLoader` to resolve fields instead of instantiating a new `Model`.
- chore: Add iterable type hints.
- chore!: Bump minimum WPGraphQL version to v1.26.0.
Expand Down
4 changes: 3 additions & 1 deletion src/Data/EntryObjectMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public static function get_field_value_input( array $args, array $form, bool $is
case 'calculation':
$field_value_input = FieldValueInput\ProductValueInput::class;
break;
case 'radio':
$field_value_input = FieldValueInput\RadioValueInput::class;
break;
case 'date':
case 'hidden':
case 'number':
Expand All @@ -79,7 +82,6 @@ public static function get_field_value_input( array $args, array $form, bool $is
case 'post_excerpt':
case 'post_title':
case 'price':
case 'radio':
case 'select':
case 'text':
case 'textarea':
Expand Down
85 changes: 85 additions & 0 deletions src/Data/FieldValueInput/RadioValueInput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Manipulates input data for Radio field values.
*
* @package WPGraphQL\GF\Data\FieldValueInput
* @since @todo
*/

declare( strict_types = 1 );

namespace WPGraphQL\GF\Data\FieldValueInput;

use GFCommon;

/**
* Class - RadioValueInput
*/
class RadioValueInput extends AbstractFieldValueInput {
/**
* {@inheritDoc}
*
* @var string
*/
protected $args;

/**
* {@inheritDoc}
*
* @var array<int|string,?string>
*/
public $value;

/**
* {@inheritDoc}
*/
protected function get_field_name(): string {
return 'value';
}

/**
* {@inheritDoc}
*
* @return array<int|string,?string>
*/
protected function prepare_value() {
$value = $this->args;

// Handle values with price.
if ( ! empty( $this->field->enablePrice ) && false === strpos( $value, '|' ) ) {
$value_key = ! empty( $this->field->enablePrice ) || ! empty( $this->field->enableChoiceValue ) ? 'value' : 'text';
$choice_key = array_search( $value, array_column( $this->field->choices, $value_key ), true );
$choice = $this->field->choices[ $choice_key ];
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) );
$value = $value . '|' . $price;
}

if ( empty( $this->field->enableOtherChoice ) ) {
return [
$this->field->id => $value,
];
}

$allowed_values = wp_list_pluck( $this->field->choices, 'value' );

if ( ! in_array( $value, $allowed_values, true ) ) {
$_POST[ $this->field->id . '_other' ] = $value;
$_POST[ $this->field->id ] = 'gf_other_choice';
return [
$this->field->id => 'gf_other_choice',
$this->field->id . '_other' => $value,
];
}

return [
$this->field->id => $value,
];
}

/**
* {@inheritDoc}
*/
public function add_value_to_submission( array &$field_values ): void {
$field_values += $this->value;
}
}
4 changes: 3 additions & 1 deletion src/Model/FormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* @property int $databaseId The database ID of the field.
* @property string $id The global Relay ID of the field.
* @property array<string,mixed>[] $inputs The inputs for the field.
* @property string $inputType The input type of the field.
* @property \GF_Field $gfField The Gravity Forms field object.
* @property int $layoutGridColumSpan The layout grid column span of the field.
*/
Expand Down Expand Up @@ -224,6 +225,7 @@ static function ( $choice ) use ( $data ) {
);
},
'databaseId' => static fn (): int => (int) $data->id,
'gfField' => static fn (): GF_Field => $data,
'id' => static fn (): string => Relay::toGlobalId( FormFieldsLoader::$name, $data->formId . ':' . $data->id ),
'inputs' => static function () use ( $data ): ?array {
// Emails fields are handled later.
Expand Down Expand Up @@ -269,7 +271,7 @@ static function ( $input ) use ( $data ) {

return $inputs;
},
'gfField' => static fn (): GF_Field => $data,
'inputType' => static fn (): string => $data->get_input_type(),
'layoutGridColumSpan' => static fn (): ?int => ! empty( $data->layoutGridColumnSpan ) ? (int) $data->layoutGridColumnSpan : null,
];
}
Expand Down
5 changes: 5 additions & 0 deletions src/Mutation/UpdateEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ public static function prepare_field_values_for_save( array $values, array $entr
$field_id = strtok( (string) $id, '.' );
$field = GFUtils::get_field_by_id( $form, (int) $field_id );

// Radio fields use the `_other` field for the other choice.
if ( 'radio' === $field->get_input_type() && 'gf_other_choice' === $value ) {
$value = $values[ $id . '_other' ];
}

// Post images can sometimes already be prepared.
if ( 'post_image' !== $field->type || is_array( $value ) ) {
$value = GFFormsModel::prepare_value( $form, $field, $value, $input_name, $entry['id'], $entry );
Expand Down
5 changes: 5 additions & 0 deletions src/Type/WPObject/FormField/FieldValue/FieldValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public static function value(): array {
return null;
}

// If its a radio field with a "other" choice on a draft entry, the value is stored in a different field.
if ( 'radio' === $source->inputType && isset( $context->gfEntry->entry[ $source->databaseId ] ) && 'gf_other_choice' === $context->gfEntry->entry[ $source->databaseId ] && isset( $context->gfEntry->entry[ $source->databaseId . '_other' ] ) ) {
return $context->gfEntry->entry[ $source->databaseId . '_other' ];
}

return $source->gfField->get_value_export( $context->gfEntry->entry, (string) $source->databaseId ) ?: null;
},
],
Expand Down
1 change: 0 additions & 1 deletion tests/_support/Helper/Wpunit.php
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,6 @@ public function getRadioFieldArgs(): array {
'description',
'descriptionPlacement',
'enableChoiceValue',
'enableOtherChoice',
'errorMessage',
'inputName',
'isRequired',
Expand Down
Loading

0 comments on commit b70ef41

Please sign in to comment.