-
Notifications
You must be signed in to change notification settings - Fork 441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor!: [WIP] Exploring a ConnectionResolver 2.0 #2749
base: develop
Are you sure you want to change the base?
Changes from all commits
cdfd1a9
1d084e8
b266d3e
f58c3e1
b3da418
f6babda
6e639de
77d99b9
37e598b
c62f63b
c2b3613
2e4f976
e008719
0847c89
b4aad63
da29d16
b8dd6a6
02c6053
cd00132
765dfcf
eeaed24
025d45e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,32 +4,25 @@ | |
|
||
use GraphQL\Error\UserError; | ||
use WPGraphQL\Utils\Utils; | ||
use WP_Comment_Query; | ||
|
||
/** | ||
* Class CommentConnectionResolver | ||
* | ||
* @package WPGraphQL\Data\Connection | ||
* @extends \WPGraphQL\Data\Connection\AbstractConnectionResolver<\WP_Comment_Query> | ||
*/ | ||
class CommentConnectionResolver extends AbstractConnectionResolver { | ||
/** | ||
* {@inheritDoc} | ||
* | ||
* @var \WP_Comment_Query | ||
*/ | ||
protected $query; | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* @throws \GraphQL\Error\UserError | ||
*/ | ||
public function get_query_args() { | ||
|
||
protected function prepare_query_args( array $args ): array { | ||
/** | ||
* Prepare for later use | ||
*/ | ||
$last = ! empty( $this->args['last'] ) ? $this->args['last'] : null; | ||
$last = ! empty( $args['last'] ) ? $args['last'] : null; | ||
|
||
$query_args = []; | ||
|
||
|
@@ -56,18 +49,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 | ||
|
@@ -113,14 +106,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'; | ||
|
||
/** | ||
|
@@ -130,28 +123,21 @@ public function get_query_args() { | |
$query_args['fields'] = 'ids'; | ||
|
||
/** | ||
* Filter the query_args that should be applied to the query. This filter is applied AFTER the input args from | ||
* the GraphQL Query have been applied and has the potential to override the GraphQL Query Input Args. | ||
* Filters the query args used by the connection. | ||
* | ||
* @param array<string,mixed> $query_args array of query_args being passed to the | ||
* @param mixed $source source passed down from the resolve tree | ||
* @param array<string,mixed> $args array of arguments input in the field as part of the GraphQL query | ||
* @param \WPGraphQL\AppContext $context object passed down the resolve tree | ||
* @param \GraphQL\Type\Definition\ResolveInfo $info info about fields passed down the resolve tree | ||
* @param array<string,mixed> $query_args The query args to be used with the executable query to get data. | ||
* @param self $resolver The AbstractConnectionResolver instance. | ||
* | ||
* @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 ); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* @return \WP_Comment_Query | ||
* @throws \Exception | ||
*/ | ||
public function get_query() { | ||
return new WP_Comment_Query( $this->query_args ); | ||
protected function query_class(): string { | ||
return \WP_Comment_Query::class; | ||
} | ||
|
||
/** | ||
|
@@ -164,26 +150,26 @@ protected function loader_name(): string { | |
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function get_ids_from_query() { | ||
public function get_ids_from_query(): array { | ||
$queried = $this->get_query(); | ||
$comments = $queried->get_comments(); | ||
/** @var int[]|string[] $ids */ | ||
$ids = ! empty( $this->query->get_comments() ) ? $this->query->get_comments() : []; | ||
$ids = ! empty( $comments ) ? $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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Method |
||
if ( ! empty( $args['where'] ) ) { | ||
// Ensure all IDs are converted to database IDs. | ||
foreach ( $args['where'] as $input_key => $input_value ) { | ||
|
@@ -238,8 +224,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 | ||
*/ | ||
|
@@ -296,9 +282,12 @@ public function sanitize_input_fields( array $args ) { | |
* This allows plugins/themes to hook in and alter what $args should be allowed to be passed | ||
* from a GraphQL Query to the get_terms query | ||
* | ||
* @param array<string,mixed> $query_args The array of query arguments | ||
* @param self $resolver The instance of the CommentConnectionResolver | ||
* | ||
* @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, $this ); | ||
|
||
return ! empty( $query_args ) && is_array( $query_args ) ? $query_args : []; | ||
} | ||
|
@@ -308,7 +297,7 @@ public function sanitize_input_fields( array $args ) { | |
* | ||
* @param int $offset The ID of the node used for the cursor offset. | ||
*/ | ||
public function is_valid_offset( $offset ) { | ||
public function is_valid_offset( $offset ): bool { | ||
return ! empty( get_comment( $offset ) ); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
<?php | ||
|
||
namespace WPGraphQL\Data\Connection; | ||
|
||
use Exception; | ||
use GraphQL\Type\Definition\ResolveInfo; | ||
use WPGraphQL\AppContext; | ||
|
||
/** | ||
* Class ConnectionResolverShim - Shim for ConnectionResolver 2.0 | ||
* | ||
* Note: This is NOT a true shim, but rather illustrates the changes that need to be made to convert classes to use the new ConnectionResolver. | ||
* | ||
* Issues like changes in method signatures (visibility, arg/return types, etc) are not addressed here. | ||
* | ||
* @package WPGraphQL\Data\Connection | ||
* @extends \WPGraphQL\Data\Connection\AbstractConnectionResolver<mixed[]|object|mixed> | ||
*/ | ||
abstract class ConnectionResolverShim extends AbstractConnectionResolver { | ||
|
||
/** | ||
* Returns the source of the connection | ||
* | ||
* @deprecated @todo | ||
* @return mixed | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function getSource() { | ||
_deprecated_function( __METHOD__, '@todo', parent::class . '::get_source()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
return $this->get_source(); | ||
} | ||
|
||
/** | ||
* Get the loader name | ||
* | ||
* @deprecated @todo | ||
* | ||
* @return \WPGraphQL\Data\Loader\AbstractDataLoader | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
protected function getLoader() { | ||
_deprecated_function( __METHOD__, '@todo', parent::class . '::get_loader()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
|
||
return $this->get_loader(); | ||
} | ||
|
||
/** | ||
* Returns the $args passed to the connection | ||
* | ||
* @deprecated @todo | ||
* | ||
* @return array<string,mixed> | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function getArgs(): array { | ||
_deprecated_function( __METHOD__, '1.11.0', static::class . '::get_args()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
return $this->get_args(); | ||
} | ||
|
||
/** | ||
* Returns the AppContext of the connection | ||
* | ||
* @deprecated @todo | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function getContext(): AppContext { | ||
_deprecated_function( __METHOD__, '@todo', parent::class . '::get_context()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
return $this->get_context(); | ||
} | ||
|
||
/** | ||
* Returns the ResolveInfo of the connection | ||
* | ||
* @deprecated @todo | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function getInfo(): ResolveInfo { | ||
_deprecated_function( __METHOD__, '@todo', parent::class . '::get_info()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
return $this->get_info(); | ||
} | ||
|
||
/** | ||
* Returns whether the connection should execute | ||
* | ||
* @deprecated @todo | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function getShouldExecute(): bool { | ||
_deprecated_function( __METHOD__, '@todo', parent::class . '::get_should_execute()' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | ||
return $this->get_should_execute(); | ||
} | ||
|
||
/** | ||
* @param string $key The key of the query arg to set | ||
* @param mixed $value The value of the query arg to set | ||
* | ||
* @return static | ||
* | ||
* @deprecated 0.3.0 | ||
* | ||
* @codeCoverageIgnore | ||
*/ | ||
public function setQueryArg( $key, $value ) { | ||
_deprecated_function( __METHOD__, '0.3.0', static::class . '::set_query_arg()' ); | ||
|
||
return $this->set_query_arg( $key, $value ); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* Method `get_loader_name()` is no longer abstract. | ||
* | ||
* Overloading should be done via `loader_name()`. | ||
* | ||
* @throws \Exception | ||
*/ | ||
protected function loader_name(): string { | ||
throw new Exception( | ||
sprintf( | ||
// translators: %s is the name of the connection resolver class. | ||
esc_html__( 'Class %s does not implement a valid method `loader_name()`.', 'wp-graphql' ), | ||
static::class | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* Method `get_query_args()` is no longer abstract. | ||
* | ||
* Overloading should be done via `prepare_query_args()`. | ||
* | ||
* @throws \Exception | ||
*/ | ||
protected function prepare_query_args( array $args ): array { | ||
throw new Exception( | ||
sprintf( | ||
// translators: %s is the name of the connection resolver class. | ||
esc_html__( 'Class %s does not implement a valid method `prepare_query_args()`.', 'wp-graphql' ), | ||
static::class | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Method `get_query()` is no longer abstract. Overloading (if necesary) should be done via `query()` and `query_class()`. | ||
*/ | ||
|
||
/** | ||
* Method `should_execute()` is now protected and no longer abstract. It defaults to `true`. | ||
* | ||
* Overload `should_execute()` or `pre_should_execute()` should only occur if there is a reason the connecton should not always execute.. | ||
*/ | ||
|
||
/** | ||
* This method is now abstract. | ||
* | ||
* {@inheritDoc} | ||
* | ||
* @throws \Exception | ||
*/ | ||
public function get_ids_from_query(): array { | ||
throw new Exception( | ||
sprintf( | ||
// translators: %s is the name of the connection resolver class. | ||
esc_html__( 'Class %s does not implement a valid method `get_ids_from_query()`.', 'wp-graphql' ), | ||
static::class | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* This returns the offset to be used in the $query_args based on the $args passed to the | ||
* GraphQL query. | ||
* | ||
* @deprecated 1.9.0 | ||
* | ||
* @codeCoverageIgnore | ||
* | ||
* @return int|mixed | ||
*/ | ||
public function get_offset() { | ||
_deprecated_function( __METHOD__, '1.9.0', static::class . '::get_offset_for_cursor()' ); | ||
|
||
$args = $this->get_args(); | ||
|
||
// Using shorthand since this is for deprecated code. | ||
$cursor = $args['after'] ?? null; | ||
$cursor = $cursor ?: ( $args['before'] ?? null ); | ||
|
||
return $this->get_offset_for_cursor( $cursor ); | ||
} | ||
|
||
/** | ||
* Method get_nodes() should now be overloaded `prepare_nodes()`. | ||
*/ | ||
|
||
/** | ||
* Method `get_edges()` should be overloaded `prepare_edges()`. | ||
*/ | ||
|
||
/** | ||
* Method `get_page_info()` should now be overloaded via `prepare_page_info()`. | ||
*/ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function
prepare_query_args
has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.