Skip to content

Commit e68b7c0

Browse files
authored
fix: backwards pagination and filtering in FormFieldsConnectionResolver (#420)
1 parent a050062 commit e68b7c0

File tree

5 files changed

+521
-26
lines changed

5 files changed

+521
-26
lines changed

src/Data/Connection/FormFieldsConnectionResolver.php

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ protected function loader_name(): string {
6767
*/
6868
public function is_valid_offset( $offset ) {
6969
foreach ( $this->form_fields as $field ) {
70-
if ( $field->id === $offset ) {
70+
if ( (int) $field->id === (int) $offset ) {
7171
return true;
7272
}
7373
}
@@ -87,7 +87,41 @@ public function get_ids_from_query() {
8787

8888
$ids = [];
8989
foreach ( $queried as $item ) {
90-
$ids[ $item->id ] = $item->id;
90+
$ids[ (int) $item->id ] = $item->id;
91+
}
92+
93+
return $ids;
94+
}
95+
96+
/**
97+
* {@inheritDoc}
98+
*/
99+
public function apply_cursors_to_ids( array $ids ) {
100+
if ( empty( $ids ) ) {
101+
return [];
102+
}
103+
$args = $this->get_args();
104+
105+
// First we slice the array from the front.
106+
if ( ! empty( $args['after'] ) ) {
107+
$offset = $this->get_offset_for_cursor( $args['after'] );
108+
$index = $this->get_array_index_for_offset( $offset, $ids );
109+
110+
if ( false !== $index ) {
111+
// We want to start with the first id after the index.
112+
$ids = array_slice( $ids, $index + 1, null, true );
113+
}
114+
}
115+
116+
// Then we slice the array from the back.
117+
if ( ! empty( $args['before'] ) ) {
118+
$offset = $this->get_offset_for_cursor( $args['before'] );
119+
$index = $this->get_array_index_for_offset( $offset, $ids );
120+
121+
if ( false !== $index ) {
122+
// We want to end with the id before the index.
123+
$ids = array_slice( $ids, 0, $index, true );
124+
}
91125
}
92126

93127
return $ids;
@@ -97,25 +131,31 @@ public function get_ids_from_query() {
97131
* {@inheritDoc}
98132
*/
99133
protected function prepare_args( array $args ): array {
100-
// Ensure that the ids are an array.
101-
if ( isset( $args['where']['ids'] ) && ! is_array( $args['where']['ids'] ) ) {
102-
$args['where']['ids'] = [ $args['where']['ids'] ];
134+
// Ensure that the ids are an array of ints.
135+
if ( isset( $args['where']['ids'] ) ) {
136+
if ( ! is_array( $args['where']['ids'] ) ) {
137+
$args['where']['ids'] = [ $args['where']['ids'] ];
138+
}
103139

104140
// Sanitize the IDs.
105141
$args['where']['ids'] = array_map( 'absint', $args['where']['ids'] );
106142
}
107143

108-
// Ensure that Admin labels are an array.
109-
if ( isset( $args['where']['adminLabels'] ) && ! is_array( $args['where']['adminLabels'] ) ) {
110-
$args['where']['adminLabels'] = [ $args['where']['adminLabels'] ];
144+
// Ensure that Admin labels are an array of strings.
145+
if ( isset( $args['where']['adminLabels'] ) ) {
146+
if ( ! is_array( $args['where']['adminLabels'] ) ) {
147+
$args['where']['adminLabels'] = [ $args['where']['adminLabels'] ];
148+
}
111149

112150
// Sanitize the Admin labels.
113151
$args['where']['adminLabels'] = array_map( 'sanitize_text_field', $args['where']['adminLabels'] );
114152
}
115153

116-
// Ensure that Field types are an array.
117-
if ( isset( $args['where']['fieldTypes'] ) && ! is_array( $args['where']['fieldTypes'] ) ) {
118-
$args['where']['fieldTypes'] = [ $args['where']['fieldTypes'] ];
154+
// Ensure that Field types are an array of strings.
155+
if ( isset( $args['where']['fieldTypes'] ) ) {
156+
if ( ! is_array( $args['where']['fieldTypes'] ) ) {
157+
$args['where']['fieldTypes'] = [ $args['where']['fieldTypes'] ];
158+
}
119159

120160
// Sanitize the Field types.
121161
$args['where']['fieldTypes'] = array_map( 'sanitize_text_field', $args['where']['fieldTypes'] );
@@ -149,22 +189,40 @@ protected function query( array $query_args ): array {
149189

150190
// Filter by IDs.
151191
if ( ! empty( $query_args['ids'] ) ) {
152-
$fields = array_filter( $fields, static fn ( $field ) => in_array( (int) $field['id'], $query_args['ids'], true ) );
192+
$fields = array_filter( $fields, static fn ( \GF_Field $field ) => isset( $field->id ) && in_array( (int) $field->id, $query_args['ids'], true ) );
153193
}
154194

155195
// Filter by Admin labels.
156196
if ( ! empty( $query_args['adminLabels'] ) ) {
157-
$fields = array_filter( $fields, static fn ( $field ) => in_array( $field['adminLabel'], $query_args['adminLabels'], true ) );
197+
$fields = array_filter( $fields, static fn ( \GF_Field $field ) => isset( $field->adminLabel ) && in_array( $field->adminLabel, $query_args['adminLabels'], true ) );
158198
}
159199

160200
// Filter by Field types.
161201
if ( ! empty( $query_args['fieldTypes'] ) ) {
162-
$fields = array_filter( $fields, static fn ( $field ) => in_array( $field['type'], $query_args['fieldTypes'], true ) );
202+
$fields = array_filter( $fields, static fn ( \GF_Field $field ) => isset( $field->type ) && in_array( $field->type, $query_args['fieldTypes'], true ) );
163203
}
164204

165205
// Filter by Page number.
206+
$has_page_number = false;
166207
if ( ! empty( $query_args['pageNumber'] ) ) {
167-
$fields = array_filter( $fields, static fn ( $field ) => $query_args['pageNumber'] === (int) $field['pageNumber'] );
208+
$filtered_fields = array_filter(
209+
$fields,
210+
static function ( \GF_Field $field ) use ( $query_args, &$has_page_number ) {
211+
if ( ! isset( $field->pageNumber ) ) {
212+
return false;
213+
}
214+
215+
// Set the flag to true if the page number is found.
216+
$has_page_number = true;
217+
218+
return $query_args['pageNumber'] === (int) $field->pageNumber;
219+
}
220+
);
221+
222+
// Dont use filtered fileds if the form isnt paged.
223+
if ( $has_page_number || 1 < $query_args['pageNumber'] ) {
224+
$fields = $filtered_fields;
225+
}
168226
}
169227

170228
return $fields;

tests/wpunit/EmailFieldTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ public function generate_fields(): array {
7070

7171
// Mimic the Form Field model.
7272
// $field->inputs = [
73-
// [
74-
// 'autocompleteAttribute' => $field->autocompleteAttribute ?? null,
75-
// 'defaultValue' => $field->defaultValue ?? null,
76-
// 'customLabel' => $field->customLabel ?? null,
77-
// 'id' => $field->id ?? null,
78-
// 'label' => $field->label ?? null,
79-
// 'name' => $field->inputName ?? null,
80-
// 'placeholder' => $field->placeholder ?? null,
81-
// ]
73+
// [
74+
// 'autocompleteAttribute' => $field->autocompleteAttribute ?? null,
75+
// 'defaultValue' => $field->defaultValue ?? null,
76+
// 'customLabel' => $field->customLabel ?? null,
77+
// 'id' => $field->id ?? null,
78+
// 'label' => $field->label ?? null,
79+
// 'name' => $field->inputName ?? null,
80+
// 'placeholder' => $field->placeholder ?? null,
81+
// ]
8282
// ];
8383

8484
return [ $field ];

tests/wpunit/EmailFieldWithConfirmationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function field_helper() {
5858
* Generates the form fields from factory. Must be wrappend in an array.
5959
*/
6060
public function generate_fields(): array {
61-
$field = $this->factory->field->create(
61+
$field = $this->factory->field->create(
6262
array_merge(
6363
$this->property_helper->values,
6464
[ 'emailConfirmEnabled' => true ],

tests/wpunit/FormConnectionQueriesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public function testBackwardPagination() {
222222
$this->assertEquals( true, $actual['data']['gfForms']['pageInfo']['hasNextPage'] );
223223

224224
/**
225-
* Test the last two results are equal to `last:2`.
225+
* Test the last two results are equal to `first:2`.
226226
*/
227227
$variables = [
228228
'first' => 2,

0 commit comments

Comments
 (0)