Skip to content

Commit

Permalink
dev: refactor AbstractConnectionResolver::get_args() to `::prepare_…
Browse files Browse the repository at this point in the history
…args()`
  • Loading branch information
justlevine committed May 4, 2024
1 parent f6babda commit 77d99b9
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 105 deletions.
55 changes: 35 additions & 20 deletions src/Data/Connection/AbstractConnectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ abstract class AbstractConnectionResolver {
*
* Filterable by `graphql_connection_args`.
*
* @var array<string,mixed>
* @var ?array<string,mixed>
*/
protected $args;

Expand Down Expand Up @@ -113,6 +113,8 @@ abstract class AbstractConnectionResolver {

/**
* @var mixed[]
*
* @deprecated @todo This is an artifact and is unused. It will be removed in a future release.
*/
protected $items;

Expand Down Expand Up @@ -172,9 +174,9 @@ public function __construct( $source, array $args, AppContext $context, ResolveI

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

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

/**
*
* Filters the GraphQL args before they are used in get_query_args().
*
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
Expand All @@ -194,7 +195,7 @@ public function __construct( $source, array $args, AppContext $context, ResolveI
*
* @since 1.11.0
*/
$this->args = apply_filters( 'graphql_connection_args', $this->get_args(), $this, $this->get_unfiltered_args() );
$this->args = apply_filters( 'graphql_connection_args', $this->args, $this, $this->get_unfiltered_args() );

// Get the query amount for the connection.
$this->query_amount = $this->get_query_amount();
Expand Down Expand Up @@ -223,17 +224,6 @@ protected function loader_name(): string {
return '';
}

/**
* Returns the $args passed to the connection.
*
* Useful for modifying the $args before they are passed to $this->get_query_args().
*
* @return array<string,mixed>
*/
public function get_args(): array {
return $this->args;
}

/**
* Get_query_args
*
Expand Down Expand Up @@ -285,6 +275,19 @@ protected function pre_should_execute( $source, array $args, AppContext $context
return $should_execute;
}

/**
* Prepares the GraphQL args for use by the connection.
*
* Useful for modifying the $args before they are passed to $this->get_query_args().
*
* @param array<string,mixed> $args The GraphQL input args to prepare.
*
* @return array<string,mixed>
*/
protected function prepare_args( array $args ): array {
return $args;
}

/**
* The maximum number of items that should be returned by the query.
*
Expand Down Expand Up @@ -458,7 +461,6 @@ public function get_loader_name() {
return $this->loader_name;
}


/**
* Returns the $args passed to the connection, before any modifications.
*
Expand All @@ -468,6 +470,19 @@ public function get_unfiltered_args(): array {
return $this->unfiltered_args;
}

/**
* Returns the $args passed to the connection.
*
* @return array<string,mixed>
*/
public function get_args(): array {
if ( ! isset( $this->args ) ) {
$this->args = $this->prepare_args( $this->get_unfiltered_args() );
}

return $this->args;
}

/**
* Returns the amount of items to query from the database.
*
Expand All @@ -493,7 +508,7 @@ public function get_query_amount() {
*
* @since 0.0.6
*/
$max_query_amount = (int) apply_filters( 'graphql_connection_max_query_amount', $this->max_query_amount(), $this->source, $this->args, $this->context, $this->info );
$max_query_amount = (int) apply_filters( 'graphql_connection_max_query_amount', $this->max_query_amount(), $this->source, $this->get_args(), $this->context, $this->info );

// We don't want the requested amount to be lower than 0.
$requested_query_amount = (int) max(
Expand Down Expand Up @@ -809,8 +824,8 @@ function () {
*
* This filter allows additional fields to be returned to the connection resolver
*
* @param ?array<string,mixed> $connection The connection data being returned. A single edge or null if the connection is one-to-one.
* @param self $resolver The instance of the connection resolver
* @param ?array<string,mixed> $connection The connection data being returned. A single edge or null if the connection is one-to-one.
* @param self $resolver The instance of the connection resolver
*/
return apply_filters( 'graphql_connection', $connection, $this );
}
Expand Down
37 changes: 18 additions & 19 deletions src/Data/Connection/CommentConnectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ class CommentConnectionResolver extends AbstractConnectionResolver {
* @throws \GraphQL\Error\UserError
*/
public function get_query_args() {
$args = $this->get_args();

/**
* Prepare for later use
*/
$last = ! empty( $this->args['last'] ) ? $this->args['last'] : null;
$last = ! empty( $args['last'] ) ? $args['last'] : null;

$query_args = [];

Expand All @@ -56,18 +57,18 @@ public function get_query_args() {
$query_args['orderby'] = 'comment_date';

/**
* Take any of the $this->args that were part of the GraphQL query and map their
* Take any of the $args that were part of the GraphQL query and map their
* GraphQL names to the WP_Term_Query names to be used in the WP_Term_Query
*
* @since 0.0.5
*/
$input_fields = [];
if ( ! empty( $this->args['where'] ) ) {
$input_fields = $this->sanitize_input_fields( $this->args['where'] );
if ( ! empty( $args['where'] ) ) {
$input_fields = $this->sanitize_input_fields( $args['where'] );
}

/**
* Merge the default $query_args with the $this->args that were entered
* Merge the default $query_args with the $args that were entered
* in the query.
*
* @since 0.0.5
Expand Down Expand Up @@ -113,14 +114,14 @@ public function get_query_args() {
$query_args['graphql_before_cursor'] = $this->get_before_offset();

/**
* Pass the graphql $this->args to the WP_Query
* Pass the graphql $args to the WP_Query
*/
$query_args['graphql_args'] = $this->args;
$query_args['graphql_args'] = $args;

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

/**
Expand All @@ -141,7 +142,7 @@ public function get_query_args() {
*
* @since 0.0.6
*/
return apply_filters( 'graphql_comment_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
return apply_filters( 'graphql_comment_connection_query_args', $query_args, $this->source, $args, $this->context, $this->info );
}

/**
Expand Down Expand Up @@ -169,21 +170,19 @@ public function get_ids_from_query() {
$ids = ! empty( $this->query->get_comments() ) ? $this->query->get_comments() : [];

// If we're going backwards, we need to reverse the array.
if ( ! empty( $this->args['last'] ) ) {
$args = $this->get_args();

if ( ! empty( $args['last'] ) ) {
$ids = array_reverse( $ids );
}

return $ids;
}

/**
* Filters the GraphQL args before they are used in get_query_args().
*
* @return array<string,mixed>
* {@inheritDoc}
*/
public function get_args(): array {
$args = $this->get_unfiltered_args();

protected function prepare_args( array $args ): array {
if ( ! empty( $args['where'] ) ) {
// Ensure all IDs are converted to database IDs.
foreach ( $args['where'] as $input_key => $input_value ) {
Expand Down Expand Up @@ -238,8 +237,8 @@ static function ( $id ) {
/**
* Filters the GraphQL args before they are used in get_query_args().
*
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
* @param \WPGraphQL\Data\Connection\CommentConnectionResolver $connection_resolver Instance of the ConnectionResolver
* @param array<string,mixed> $args The GraphQL args passed to the resolver.
* @param self $resolver Instance of the ConnectionResolver
*
* @since 1.11.0
*/
Expand Down Expand Up @@ -298,7 +297,7 @@ public function sanitize_input_fields( array $args ) {
*
* @since 0.0.5
*/
$query_args = apply_filters( 'graphql_map_input_fields_to_wp_comment_query', $query_args, $args, $this->source, $this->args, $this->context, $this->info );
$query_args = apply_filters( 'graphql_map_input_fields_to_wp_comment_query', $query_args, $args, $this->source, $this->get_args(), $this->context, $this->info );

return ! empty( $query_args ) && is_array( $query_args ) ? $query_args : [];
}
Expand Down
14 changes: 8 additions & 6 deletions src/Data/Connection/MenuConnectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,26 @@ public function get_query_args() {
'fields' => 'ids',
];

if ( ! empty( $this->args['where']['slug'] ) ) {
$term_args['slug'] = $this->args['where']['slug'];
$args = $this->get_args();

if ( ! empty( $args['where']['slug'] ) ) {
$term_args['slug'] = $args['where']['slug'];
$term_args['include'] = null;
}

$theme_locations = get_nav_menu_locations();

// If a location is specified in the args, use it
if ( ! empty( $this->args['where']['location'] ) ) {
if ( ! empty( $args['where']['location'] ) ) {
// Exclude unset and non-existent locations
$term_args['include'] = ! empty( $theme_locations[ $this->args['where']['location'] ] ) ? $theme_locations[ $this->args['where']['location'] ] : -1;
$term_args['include'] = ! empty( $theme_locations[ $args['where']['location'] ] ) ? $theme_locations[ $args['where']['location'] ] : -1;
// If the current user cannot edit theme options
} elseif ( ! current_user_can( 'edit_theme_options' ) ) {
$term_args['include'] = array_values( $theme_locations );
}

if ( ! empty( $this->args['where']['id'] ) ) {
$term_args['include'] = $this->args['where']['id'];
if ( ! empty( $args['where']['id'] ) ) {
$term_args['include'] = $args['where']['id'];
}

$query_args = parent::get_query_args();
Expand Down
20 changes: 10 additions & 10 deletions src/Data/Connection/MenuItemConnectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,36 @@ public function __construct( $source, array $args, AppContext $context, ResolveI
* {@inheritDoc}
*/
public function get_query_args() {
$args = $this->get_args();

/**
* Prepare for later use
*/
$last = ! empty( $this->args['last'] ) ? $this->args['last'] : null;
$last = ! empty( $args['last'] ) ? $args['last'] : null;

$menu_locations = get_theme_mod( 'nav_menu_locations' );

$query_args = parent::get_query_args();
$query_args['orderby'] = 'menu_order';
$query_args['order'] = isset( $last ) ? 'DESC' : 'ASC';

if ( isset( $this->args['where']['parentDatabaseId'] ) ) {
if ( isset( $args['where']['parentDatabaseId'] ) ) {
$query_args['meta_key'] = '_menu_item_menu_item_parent';
$query_args['meta_value'] = (int) $this->args['where']['parentDatabaseId']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
$query_args['meta_value'] = (int) $args['where']['parentDatabaseId']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
}

if ( ! empty( $this->args['where']['parentId'] ) || ( isset( $this->args['where']['parentId'] ) && 0 === (int) $this->args['where']['parentId'] ) ) {
if ( ! empty( $args['where']['parentId'] ) || ( isset( $args['where']['parentId'] ) && 0 === (int) $args['where']['parentId'] ) ) {
$query_args['meta_key'] = '_menu_item_menu_item_parent';
$query_args['meta_value'] = $this->args['where']['parentId']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
$query_args['meta_value'] = $args['where']['parentId']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
}

// Get unique list of location term IDs as the default limitation of locations to allow public queries for.
// Public queries should only be allowed to query for Menu Items assigned to a Menu Location.
$locations = is_array( $menu_locations ) && ! empty( $menu_locations ) ? array_unique( array_values( $menu_locations ) ) : [];

// If the location argument is set, set the argument to the input argument
if ( ! empty( $this->args['where']['location'] ) ) {
$locations = isset( $menu_locations[ $this->args['where']['location'] ] ) ? [ $menu_locations[ $this->args['where']['location'] ] ] : []; // We use an empty array to prevent fetching all media items if the location has no items assigned.
if ( ! empty( $args['where']['location'] ) ) {
$locations = isset( $menu_locations[ $args['where']['location'] ] ) ? [ $menu_locations[ $args['where']['location'] ] ] : []; // We use an empty array to prevent fetching all media items if the location has no items assigned.

} elseif ( current_user_can( 'edit_theme_options' ) ) {
// If the $locations are NOT set, let a user with proper capability query all menu items.
Expand Down Expand Up @@ -79,9 +81,7 @@ public function get_query_args() {
/**
* {@inheritDoc}
*/
public function get_args(): array {
$args = $this->get_unfiltered_args();

public function prepare_args( array $args ): array {
if ( ! empty( $args['where'] ) ) {
// Ensure all IDs are converted to database IDs.
foreach ( $args['where'] as $input_key => $input_value ) {
Expand Down
21 changes: 13 additions & 8 deletions src/Data/Connection/PluginConnectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ public function get_ids_from_query() {
* {@inheritDoc}
*/
public function get_query_args() {
if ( ! empty( $this->args['where']['status'] ) ) {
$this->args['where']['stati'] = [ $this->args['where']['status'] ];
} elseif ( ! empty( $this->args['where']['stati'] ) && is_string( $this->args['where']['stati'] ) ) {
$this->args['where']['stati'] = [ $this->args['where']['stati'] ];
$args = $this->get_args();

if ( ! empty( $args['where']['status'] ) ) {
$args['where']['stati'] = [ $args['where']['status'] ];
} elseif ( ! empty( $args['where']['stati'] ) && is_string( $args['where']['stati'] ) ) {
$args['where']['stati'] = [ $args['where']['stati'] ];
}

return $this->args;
return $args;
}

/**
Expand All @@ -69,6 +71,9 @@ public function get_query() {
return [];
}

// Get the GraphQL args for later.
$args = $this->get_args();

// Holds the plugin names sorted by status. The other ` status => [ plugin_names ] ` will be added later.
$plugins_by_status = [
'mustuse' => array_flip( array_keys( $plugins['mustuse'] ) ),
Expand All @@ -81,7 +86,7 @@ public function get_query() {
$show_network_plugins = apply_filters( 'show_network_active_plugins', current_user_can( 'manage_network_plugins' ) );

// Store the plugin stati as array keys for performance.
$active_stati = ! empty( $this->args['where']['stati'] ) ? array_flip( $this->args['where']['stati'] ) : [];
$active_stati = ! empty( $args['where']['stati'] ) ? array_flip( $args['where']['stati'] ) : [];

// Get additional plugin info.
$upgradable_list = $can_update && isset( $active_stati['upgrade'] ) ? get_site_transient( 'update_plugins' ) : [];
Expand Down Expand Up @@ -196,9 +201,9 @@ public function get_query() {
// If plugins exist for the filter, flatten and return them. Otherwise, return the full list.
$filtered_plugins = ! empty( $filtered_plugins ) ? array_merge( [], ...$filtered_plugins ) : $plugins_by_status['all'];

if ( ! empty( $this->args['where']['search'] ) ) {
if ( ! empty( $args['where']['search'] ) ) {
// Filter by search args.
$s = sanitize_text_field( $this->args['where']['search'] );
$s = sanitize_text_field( $args['where']['search'] );
$matches = array_keys(
array_filter(
$all_plugins,
Expand Down

0 comments on commit 77d99b9

Please sign in to comment.