Skip to content

Conversation

justlevine
Copy link
Collaborator

@justlevine justlevine commented May 21, 2025

What does this implement/fix? Explain your changes.

This PR refactors WPInterfaceTrait to improve the recursive handling of inherited interfaces.

The code quality and cyclomatic complexity of the class has been improved as well.

Does this close any currently open issues?

Any other comments?

image

@justlevine justlevine requested a review from Copilot May 21, 2025 21:36
Copilot

This comment was marked as outdated.

@jasonbahl
Copy link
Collaborator

@justlevine thanks for the PR! I'll take a look this evening or tomorrow and share any thoughts I might have 🙏🏻

@coveralls
Copy link

coveralls commented May 21, 2025

Coverage Status

coverage: 84.17% (+0.03%) from 84.14%
when pulling 2f84d5b on justlevine:fix/cleanup-WPInterfaceTrait-logic
into ccdffe1 on wp-graphql:develop.

@justlevine justlevine marked this pull request as ready for review May 21, 2025 22:10
@justlevine justlevine added type: bug Issue that causes incorrect or unexpected behavior status: in review Awaiting review before merging or closing needs: reviewer response This needs the attention of a codeowner or maintainer regression Bug that causes a regression to a previously working feature labels May 21, 2025
@justlevine justlevine force-pushed the fix/cleanup-WPInterfaceTrait-logic branch from aed7e55 to e21f262 Compare June 2, 2025 21:39
@jasonbahl
Copy link
Collaborator

@justlevine this looks good. I'll see if I can get a test written for this case tomorrow 🤞🏻

@justlevine justlevine requested a review from jasonbahl June 7, 2025 00:17
jasonbahl added a commit to justlevine/wp-graphql that referenced this pull request Jun 16, 2025
jasonbahl added a commit to jasonbahl/wp-graphql that referenced this pull request Jun 16, 2025
*
* @return array<\GraphQL\Type\Definition\InterfaceType>
*/
private function get_all_interfaces( InterfaceType $interface_type, TypeRegistry $registry ): array {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function get_all_interfaces has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do, why do we need it, how is it different than the all the other times in this (and implementing) class that'were trying to get interfaces?

@jasonbahl
Copy link
Collaborator

@justlevine I pushed up some tests that pass on this PR but fail on Master (see #3388).

I made some tweaks to the WPInterfaceTrait as well. Might be good to confirm that my changes to help support the test cases are also practical for your real-world scenarios.

@justlevine justlevine requested a review from Copilot June 16, 2025 18:02
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the WPInterfaceTrait to improve recursive handling of inherited interfaces and field configurations. Key changes include:

  • Fallback to parent interfaces when none are explicitly provided.
  • Recursive resolution of inherited interfaces with improved validation.
  • More robust merging of field configurations from implemented interfaces.
Comments suppressed due to low confidence (1)

src/Type/WPInterfaceTrait.php:133

  • The docblock uses '@@param-out' which appears to be a typo. It should likely be corrected to '@param-out' to adhere to proper docblock conventions.
* @@param-out array<string, \GraphQL\Type\Definition\InterfaceType> $target_interfaces The array to add interfaces to (passed by reference).

Comment on lines +60 to +63
// We use array_unique as a final safeguard against duplicate entries.
// While we're already using interface names as array keys which generally prevents duplicates,
// this provides an extra layer of protection for edge cases or future modifications.
return array_unique( $implemented_interfaces );
Copy link
Preview

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since $implemented_interfaces is built as an associative array keyed by interface names, using array_unique may be redundant. Consider removing it or using array_values if a sequentially indexed array is needed.

Suggested change
// We use array_unique as a final safeguard against duplicate entries.
// While we're already using interface names as array keys which generally prevents duplicates,
// this provides an extra layer of protection for edge cases or future modifications.
return array_unique( $implemented_interfaces );
// Since $implemented_interfaces is an associative array keyed by interface names,
// duplicates are inherently prevented. We return the values as a sequentially indexed array.
return array_values( $implemented_interfaces );

Copilot uses AI. Check for mistakes.

@justlevine
Copy link
Collaborator Author

@jasonbahl I'm having trouble making sense of the diff from mobile, will get to the computer to review shortly.

Comment on lines 189 to 205
foreach ( $fields as $field_name => $field ) {
$merged_field_config = $this->inherit_field_config_from_interface( $field_name, $field, $interface_fields );
// Get all interfaces that define this field
$interfaces_with_field = [];
foreach ( $this->getInterfaces() as $interface ) {
if ( ! $interface instanceof InterfaceType ) {
$interface = $type_registry->get_type( $interface );
}

if ( null === $merged_field_config ) {
unset( $fields[ $field_name ] );
continue;
if ( ! $interface instanceof InterfaceType ) {
continue;
}

$interface_fields = $interface->getFields();
if ( isset( $interface_fields[ $field_name ] ) ) {
$interfaces_with_field[] = $interface;
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from what happens in ::get_fields_from_implemented_interfaces() ?

Comment on lines 207 to 223
// If this field is defined in any interfaces, merge their configs
if ( ! empty( $interfaces_with_field ) ) {
$merged_field_config = $field;
foreach ( $interfaces_with_field as $interface ) {
$interface_fields = $interface->getFields();
$interface_field = $interface_fields[ $field_name ];
$merged_field_config = $this->inherit_field_config_from_interface( $field_name, $merged_field_config, [ $field_name => $interface_field->config ] );
}

if ( null === $merged_field_config ) {
unset( $fields[ $field_name ] );
continue;
}

// Update the field.
$fields[ $field_name ] = $merged_field_config;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this level of nesting do?

@@ -227,20 +252,65 @@ private function get_fields_from_implemented_interfaces( TypeRegistry $registry
continue;
}

$interface_config_fields = $interface_type->getFields();
// Get all interfaces in the inheritance chain
$all_interfaces = $this->get_all_interfaces( $interface_type, $registry );
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but ::get_type() gives us the constructed type with all the resolved fields (including from the interface) because of our get_fields() this seems like weird recursion or am I missing something?

@justlevine justlevine force-pushed the fix/cleanup-WPInterfaceTrait-logic branch from 8920bbe to f81098b Compare June 16, 2025 18:56
@justlevine
Copy link
Collaborator Author

(force-push was a rebase on develop to test again GF with the other regression merged)

@justlevine
Copy link
Collaborator Author

@jasonbahl tests are still passing with WPGraphQL for GF, so whatever changes you made seem to have no breaking effect there, but I havn't performance tested the new code.

However, even after pulling I cannot make sense of the changes you made. I left feedback how I could above since my availability is limited.

I'd also stress that the PR (before your last commit) was aimed at a regression in WPGraphQL v2.0x that has prevented dozens of teams that I'm aware of from upgrading their dev environments, and affects production environments for anything relying on WPGraphQL Smart Cache + varying extensions. If these change's relevant to addressing the regression - maybe they can happen in a separate PR (perhaps even after the patch release has been cut?)

@jasonbahl
Copy link
Collaborator

jasonbahl commented Jun 16, 2025

@jasonbahl tests are still passing with WPGraphQL for GF, so whatever changes you made seem to have no breaking effect there, but I havn't performance tested the new code.

However, even after pulling I cannot make sense of the changes you made. I left feedback how I could above since my availability is limited.

I'd also stress that the PR (before your last commit) was aimed at a regression in WPGraphQL v2.0x that has prevented dozens of teams that I'm aware of from upgrading their dev environments, and affects production environments for anything relying on WPGraphQL Smart Cache + varying extensions. If these change's relevant to addressing the regression - maybe they can happen in a separate PR (perhaps even after the patch release has been cut?)

@justlevine ok, I was working on adding some test cases for what I believe were some missing cases with the merging of interfaces.

The test testInterfaceFieldInheritanceAndMerging is the test that fails and that I was able to address, however I've determined that the test also fails in v1.32 and other versions, so this indeed was a pre-existing bug and not something that necessarily needs to be addressed in this PR, so I can flag that test as incomplete and revert the changes I made to WPInterfaceTrait and we can follow up on this functionality in the future if we deem that it should be considered supported functionality.

Copy link

Code Climate has analyzed commit 2f84d5b and detected 2 issues on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 2

View more on Code Climate.

@jasonbahl jasonbahl merged commit f2eedea into wp-graphql:develop Jun 16, 2025
35 of 36 checks passed
@justlevine
Copy link
Collaborator Author

justlevine commented Jun 16, 2025

That test case sounds strangely similar to #3096 🤔👀🤞

jasonbahl pushed a commit that referenced this pull request Jun 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs: reviewer response This needs the attention of a codeowner or maintainer regression Bug that causes a regression to a previously working feature status: in review Awaiting review before merging or closing type: bug Issue that causes incorrect or unexpected behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants