Skip to content

Commit 6c7cb70

Browse files
authored
Merge pull request #3124 from justlevine/dev/refactor-get_args
refactor: split `AbstractConnectionResolver::get_args()` and `::get_query_args()` into `::prepare_*()` methods
2 parents 565137f + b4aad63 commit 6c7cb70

14 files changed

+200
-156
lines changed

src/Data/Connection/AbstractConnectionResolver.php

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ abstract class AbstractConnectionResolver {
3636
*
3737
* Filterable by `graphql_connection_args`.
3838
*
39-
* @var array<string,mixed>
39+
* @var ?array<string,mixed>
4040
*/
4141
protected $args;
4242

@@ -57,7 +57,9 @@ abstract class AbstractConnectionResolver {
5757
/**
5858
* The query args used to query for data to resolve the connection.
5959
*
60-
* @var array<string,mixed>
60+
* Filterable by `graphql_connection_query_args`.
61+
*
62+
* @var ?array<string,mixed>
6163
*/
6264
protected $query_args;
6365

@@ -99,9 +101,9 @@ abstract class AbstractConnectionResolver {
99101
* The Query class/array/object used to fetch the data.
100102
*
101103
* Examples:
102-
* return new WP_Query( $this->query_args );
103-
* return new WP_Comment_Query( $this->query_args );
104-
* return new WP_Term_Query( $this->query_args );
104+
* return new WP_Query( $this->get_query_args() );
105+
* return new WP_Comment_Query( $this->get_query_args() );
106+
* return new WP_Term_Query( $this->get_query_args() );
105107
*
106108
* Whatever it is will be passed through filters so that fields throughout
107109
* have context from what was queried and can make adjustments as needed, such
@@ -113,6 +115,8 @@ abstract class AbstractConnectionResolver {
113115

114116
/**
115117
* @var mixed[]
118+
*
119+
* @deprecated @todo This is an artifact and is unused. It will be removed in a future release.
116120
*/
117121
protected $items;
118122

@@ -172,9 +176,9 @@ public function __construct( $source, array $args, AppContext $context, ResolveI
172176

173177
/**
174178
* @todo This exists for b/c, where extenders may be directly accessing `$this->args` in ::get_loader() or even `::get_args()`.
175-
* We can remove this once the rest of lifecycle has been updated.
179+
* We can call it later in the lifecycle once that's no longer the case.
176180
*/
177-
$this->args = $args;
181+
$this->args = $this->get_args();
178182

179183
// Pre-check if the connection should execute so we can skip expensive logic if we already know it shouldn't execute.
180184
if ( ! $this->get_pre_should_execute( $this->source, $this->unfiltered_args, $this->context, $this->info ) ) {
@@ -185,31 +189,31 @@ public function __construct( $source, array $args, AppContext $context, ResolveI
185189
$this->loader = $this->get_loader();
186190

187191
/**
188-
*
189192
* Filters the GraphQL args before they are used in get_query_args().
190193
*
194+
* @todo We reinstantate this here for b/c. Once that is not a concern, we should relocate this filter to ::get_args().
195+
*
191196
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
192197
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver Instance of the ConnectionResolver.
193198
* @param array<string,mixed> $unfiltered_args Array of arguments input in the field as part of the GraphQL query.
194199
*
195200
* @since 1.11.0
196201
*/
197-
$this->args = apply_filters( 'graphql_connection_args', $this->get_args(), $this, $this->get_unfiltered_args() );
202+
$this->args = apply_filters( 'graphql_connection_args', $this->args, $this, $this->get_unfiltered_args() );
198203

199204
// Get the query amount for the connection.
200205
$this->query_amount = $this->get_query_amount();
201206

202207
/**
203-
* Get the Query Args. This accepts the input args and maps it to how it should be
204-
* used in the WP_Query
208+
* Filters the query args before they are used in the query.
205209
*
206-
* Filters the args
210+
* @todo We reinstantate this here for b/c. Once that is not a concern, we should relocate this filter to ::get_query_args().
207211
*
208212
* @param array<string,mixed> $query_args The query args to be used with the executable query to get data.
209213
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver Instance of the ConnectionResolver
210-
* @param array<string,mixed> $unfiltered_args Array of arguments input in the field as part of the GraphQL query.
214+
* @param array<string,mixed> $unfiltered_args Array of arguments input in the field as part of the GraphQL query.
211215
*/
212-
$this->query_args = apply_filters( 'graphql_connection_query_args', $this->get_query_args(), $this, $args );
216+
$this->query_args = apply_filters( 'graphql_connection_query_args', $this->get_query_args(), $this, $this->get_unfiltered_args() );
213217
}
214218

215219
/**
@@ -224,28 +228,30 @@ protected function loader_name(): string {
224228
}
225229

226230
/**
227-
* Returns the $args passed to the connection.
228-
*
229-
* Useful for modifying the $args before they are passed to $this->get_query_args().
231+
* Prepares the query args used to fetch the data for the connection.
230232
*
231-
* @return array<string,mixed>
232-
*/
233-
public function get_args(): array {
234-
return $this->args;
235-
}
236-
237-
/**
238-
* Get_query_args
233+
* This accepts the GraphQL args and maps them to a format that can be read by our query class.
234+
* For example, if the ConnectionResolver uses WP_Query to fetch the data, this should return $args for use in `new WP_Query( $args );`
239235
*
240-
* This method is used to accept the GraphQL Args input to the connection and return args
241-
* that can be used in the Query to the datasource.
236+
* @todo This is protected for backwards compatibility, but should be abstract and implemented by the child classes.
242237
*
243-
* For example, if the ConnectionResolver uses WP_Query to fetch the data, this
244-
* should return $args for use in `new WP_Query`
238+
* @param array<string,mixed> $args The GraphQL input args passed to the connection.
245239
*
246240
* @return array<string,mixed>
241+
*
242+
* @throws \Exception If the method is not implemented.
243+
*
244+
* @codeCoverageIgnore
247245
*/
248-
abstract public function get_query_args();
246+
protected function prepare_query_args( array $args ): array {
247+
throw new Exception(
248+
sprintf(
249+
// translators: %s is the name of the connection resolver class.
250+
esc_html__( 'Class %s does not implement a valid method `prepare_query_args()`.', 'wp-graphql' ),
251+
static::class
252+
)
253+
);
254+
}
249255

250256
/**
251257
* Get_query
@@ -296,6 +302,19 @@ protected function pre_should_execute( $source, array $args, AppContext $context
296302
return $should_execute;
297303
}
298304

305+
/**
306+
* Prepares the GraphQL args for use by the connection.
307+
*
308+
* Useful for modifying the $args before they are passed to $this->get_query_args().
309+
*
310+
* @param array<string,mixed> $args The GraphQL input args to prepare.
311+
*
312+
* @return array<string,mixed>
313+
*/
314+
protected function prepare_args( array $args ): array {
315+
return $args;
316+
}
317+
299318
/**
300319
* The maximum number of items that should be returned by the query.
301320
*
@@ -311,7 +330,7 @@ protected function max_query_amount(): int {
311330
* Each Query class in WP and potential datasource handles this differently, so each connection
312331
* resolver should handle getting the items into a uniform array of items.
313332
*
314-
* Note: This is not an abstract function to prevent backwards compatibility issues, so it
333+
* @todo: This is not an abstract function to prevent backwards compatibility issues, so it
315334
* instead throws an exception. Classes that extend AbstractConnectionResolver should
316335
* override this method, instead of AbstractConnectionResolver::get_ids().
317336
*
@@ -456,7 +475,6 @@ public function get_loader_name() {
456475
return $this->loader_name;
457476
}
458477

459-
460478
/**
461479
* Returns the $args passed to the connection, before any modifications.
462480
*
@@ -466,6 +484,19 @@ public function get_unfiltered_args(): array {
466484
return $this->unfiltered_args;
467485
}
468486

487+
/**
488+
* Returns the $args passed to the connection.
489+
*
490+
* @return array<string,mixed>
491+
*/
492+
public function get_args(): array {
493+
if ( ! isset( $this->args ) ) {
494+
$this->args = $this->prepare_args( $this->get_unfiltered_args() );
495+
}
496+
497+
return $this->args;
498+
}
499+
469500
/**
470501
* Returns the amount of items to query from the database.
471502
*
@@ -491,7 +522,7 @@ public function get_query_amount() {
491522
*
492523
* @since 0.0.6
493524
*/
494-
$max_query_amount = (int) apply_filters( 'graphql_connection_max_query_amount', $this->max_query_amount(), $this->source, $this->args, $this->context, $this->info );
525+
$max_query_amount = (int) apply_filters( 'graphql_connection_max_query_amount', $this->max_query_amount(), $this->source, $this->get_args(), $this->context, $this->info );
495526

496527
// We don't want the requested amount to be lower than 0.
497528
$requested_query_amount = (int) max(
@@ -518,6 +549,20 @@ public function get_query_amount() {
518549
return $this->query_amount;
519550
}
520551

552+
/**
553+
* Gets the query args used by the connection to fetch the data.
554+
*
555+
* @return array<string,mixed>
556+
*/
557+
public function get_query_args() {
558+
if ( ! isset( $this->query_args ) ) {
559+
// We pass $this->get_args() to ensure we're using the filtered args.
560+
$this->query_args = $this->prepare_query_args( $this->get_args() );
561+
}
562+
563+
return $this->query_args;
564+
}
565+
521566
/**
522567
* Returns whether the connection should execute.
523568
*
@@ -807,8 +852,8 @@ function () {
807852
*
808853
* This filter allows additional fields to be returned to the connection resolver
809854
*
810-
* @param ?array<string,mixed> $connection The connection data being returned. A single edge or null if the connection is one-to-one.
811-
* @param self $resolver The instance of the connection resolver
855+
* @param ?array<string,mixed> $connection The connection data being returned. A single edge or null if the connection is one-to-one.
856+
* @param self $resolver The instance of the connection resolver
812857
*/
813858
return apply_filters( 'graphql_connection', $connection, $this );
814859
}

src/Data/Connection/CommentConnectionResolver.php

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ class CommentConnectionResolver extends AbstractConnectionResolver {
2424
*
2525
* @throws \GraphQL\Error\UserError
2626
*/
27-
public function get_query_args() {
28-
27+
protected function prepare_query_args( array $args ): array {
2928
/**
3029
* Prepare for later use
3130
*/
32-
$last = ! empty( $this->args['last'] ) ? $this->args['last'] : null;
31+
$last = ! empty( $args['last'] ) ? $args['last'] : null;
3332

3433
$query_args = [];
3534

@@ -56,18 +55,18 @@ public function get_query_args() {
5655
$query_args['orderby'] = 'comment_date';
5756

5857
/**
59-
* Take any of the $this->args that were part of the GraphQL query and map their
58+
* Take any of the $args that were part of the GraphQL query and map their
6059
* GraphQL names to the WP_Term_Query names to be used in the WP_Term_Query
6160
*
6261
* @since 0.0.5
6362
*/
6463
$input_fields = [];
65-
if ( ! empty( $this->args['where'] ) ) {
66-
$input_fields = $this->sanitize_input_fields( $this->args['where'] );
64+
if ( ! empty( $args['where'] ) ) {
65+
$input_fields = $this->sanitize_input_fields( $args['where'] );
6766
}
6867

6968
/**
70-
* Merge the default $query_args with the $this->args that were entered
69+
* Merge the default $query_args with the $args that were entered
7170
* in the query.
7271
*
7372
* @since 0.0.5
@@ -113,14 +112,14 @@ public function get_query_args() {
113112
$query_args['graphql_before_cursor'] = $this->get_before_offset();
114113

115114
/**
116-
* Pass the graphql $this->args to the WP_Query
115+
* Pass the graphql $args to the WP_Query
117116
*/
118-
$query_args['graphql_args'] = $this->args;
117+
$query_args['graphql_args'] = $args;
119118

120119
// encode the graphql args as a cache domain to ensure the
121120
// graphql_args are used to identify different queries.
122121
// see: https://core.trac.wordpress.org/ticket/35075
123-
$encoded_args = wp_json_encode( $this->args );
122+
$encoded_args = wp_json_encode( $args );
124123
$query_args['cache_domain'] = ! empty( $encoded_args ) ? 'graphql:' . md5( $encoded_args ) : 'graphql';
125124

126125
/**
@@ -130,8 +129,7 @@ public function get_query_args() {
130129
$query_args['fields'] = 'ids';
131130

132131
/**
133-
* Filter the query_args that should be applied to the query. This filter is applied AFTER the input args from
134-
* the GraphQL Query have been applied and has the potential to override the GraphQL Query Input Args.
132+
* Filter the query_args that should be applied to the query.
135133
*
136134
* @param array<string,mixed> $query_args array of query_args being passed to the
137135
* @param mixed $source source passed down from the resolve tree
@@ -141,7 +139,7 @@ public function get_query_args() {
141139
*
142140
* @since 0.0.6
143141
*/
144-
return apply_filters( 'graphql_comment_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
142+
return apply_filters( 'graphql_comment_connection_query_args', $query_args, $this->source, $args, $this->context, $this->info );
145143
}
146144

147145
/**
@@ -151,7 +149,7 @@ public function get_query_args() {
151149
* @throws \Exception
152150
*/
153151
public function get_query() {
154-
return new WP_Comment_Query( $this->query_args );
152+
return new WP_Comment_Query( $this->get_query_args() );
155153
}
156154

157155
/**
@@ -169,21 +167,19 @@ public function get_ids_from_query() {
169167
$ids = ! empty( $this->query->get_comments() ) ? $this->query->get_comments() : [];
170168

171169
// If we're going backwards, we need to reverse the array.
172-
if ( ! empty( $this->args['last'] ) ) {
170+
$args = $this->get_args();
171+
172+
if ( ! empty( $args['last'] ) ) {
173173
$ids = array_reverse( $ids );
174174
}
175175

176176
return $ids;
177177
}
178178

179179
/**
180-
* Filters the GraphQL args before they are used in get_query_args().
181-
*
182-
* @return array<string,mixed>
180+
* {@inheritDoc}
183181
*/
184-
public function get_args(): array {
185-
$args = $this->get_unfiltered_args();
186-
182+
protected function prepare_args( array $args ): array {
187183
if ( ! empty( $args['where'] ) ) {
188184
// Ensure all IDs are converted to database IDs.
189185
foreach ( $args['where'] as $input_key => $input_value ) {
@@ -238,8 +234,8 @@ static function ( $id ) {
238234
/**
239235
* Filters the GraphQL args before they are used in get_query_args().
240236
*
241-
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
242-
* @param \WPGraphQL\Data\Connection\CommentConnectionResolver $connection_resolver Instance of the ConnectionResolver
237+
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
238+
* @param self $resolver Instance of the ConnectionResolver
243239
*
244240
* @since 1.11.0
245241
*/
@@ -298,7 +294,7 @@ public function sanitize_input_fields( array $args ) {
298294
*
299295
* @since 0.0.5
300296
*/
301-
$query_args = apply_filters( 'graphql_map_input_fields_to_wp_comment_query', $query_args, $args, $this->source, $this->args, $this->context, $this->info );
297+
$query_args = apply_filters( 'graphql_map_input_fields_to_wp_comment_query', $query_args, $args, $this->source, $this->get_args(), $this->context, $this->info );
302298

303299
return ! empty( $query_args ) && is_array( $query_args ) ? $query_args : [];
304300
}

src/Data/Connection/ContentTypeConnectionResolver.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function get_ids_from_query() {
3535
/**
3636
* {@inheritDoc}
3737
*/
38-
public function get_query_args() {
38+
protected function prepare_query_args( array $args ): array {
3939
// If any args are added to filter/sort the connection
4040
return [];
4141
}
@@ -46,15 +46,16 @@ public function get_query_args() {
4646
* @return string[]
4747
*/
4848
public function get_query() {
49-
if ( isset( $this->query_args['contentTypeNames'] ) && is_array( $this->query_args['contentTypeNames'] ) ) {
50-
return $this->query_args['contentTypeNames'];
49+
$query_args = $this->get_query_args();
50+
51+
if ( isset( $query_args['contentTypeNames'] ) && is_array( $query_args['contentTypeNames'] ) ) {
52+
return $query_args['contentTypeNames'];
5153
}
5254

53-
if ( isset( $this->query_args['name'] ) ) {
54-
return [ $this->query_args['name'] ];
55+
if ( isset( $query_args['name'] ) ) {
56+
return [ $query_args['name'] ];
5557
}
5658

57-
$query_args = $this->query_args;
5859
return \WPGraphQL::get_allowed_post_types( 'names', $query_args );
5960
}
6061

0 commit comments

Comments
 (0)