Skip to content

Commit f628ee9

Browse files
authored
Merge branch 'develop' into chore/misc-phpstan-types
2 parents 0fb21df + 92713f8 commit f628ee9

File tree

134 files changed

+5525
-3163
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+5525
-3163
lines changed

.changesets/2025-04-28-pr-3356.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: "feat: lazy loading fields for Object Types and Interface Types"
3+
pr: 3356
4+
author: "jasonbahl"
5+
type: "feat"
6+
breaking: false
7+
---
8+
9+
## What does this implement/fix? Explain your changes.
10+
11+
This PR introduces lazy evaluation of GraphQL field definitions through callable functions in the core type system. The key changes focus on:
12+
13+
1. Added support in \`WPInterfaceTrait\` to handle callable field definitions:
14+
\`\`\`php
15+
if ( is_callable( $config['fields'] ) ) {
16+
$config['fields'] = $config['fields']();
17+
}
18+
\`\`\`
19+
20+
2. Modified \`WPInterfaceType\` and \`WPObjectType\` to use callable functions for field definitions:
21+
\`\`\`php
22+
$config['fields'] = function () use ( $config ) {
23+
return ! empty( $this->fields ) ? $this->fields : $this->get_fields( $config, $this->type_registry );
24+
};
25+
\`\`\`
26+
27+
This architectural change defers the execution of field definitions until they are actually needed, rather than defining all fields upfront during schema initialization.
28+
29+
### Before/After Example
30+
31+
Here's an example of how the \`User\` type fields were refactored:
32+
33+
**Before:**
34+
\`\`\`php
35+
'fields' => [
36+
'id' => [
37+
'description' => __( 'The globally unique identifier for the user object.', 'wp-graphql' ),
38+
],
39+
'name' => [
40+
'type' => 'String',
41+
'description' => __( 'Display name of the user.', 'wp-graphql' ),
42+
],
43+
// ... more fields
44+
]
45+
\`\`\`
46+
47+
**After:**
48+
\`\`\`php
49+
'fields' => static function () {
50+
return [
51+
'id' => [
52+
'description' => __( 'The globally unique identifier for the user object.', 'wp-graphql' ),
53+
],
54+
'name' => [
55+
'type' => 'String',
56+
'description' => __( 'Display name of the user.', 'wp-graphql' ),
57+
],
58+
// ... more fields
59+
];
60+
}
61+
\`\`\`
62+
63+
To measure the impact of this change, we added a \`TestGetText\` class that tracks all \`__()\` function calls during schema generation and query execution. This logging shows that translations are now only executed when fields are actually queried, rather than during schema initialization.
64+
65+
\`\`\`php
66+
class TestGetText {
67+
68+
/**
69+
* @var array
70+
*/
71+
protected $gettext_log = [];
72+
73+
/**
74+
* Constructor
75+
*/
76+
public function __construct() {
77+
// Reset at the very start of schema generation
78+
add_action( 'graphql_process_http_request', [ $this, 'init_log' ], 1 );
79+
80+
// Track all translations
81+
add_filter(
82+
'gettext',
83+
function ( $text ) {
84+
$this->gettext_log[] = $text;
85+
return $text;
86+
},
87+
10,
88+
3
89+
);
90+
91+
// Add to extensions
92+
add_filter( 'graphql_request_results', [ $this, 'add_to_extensions' ], 10, 1 );
93+
}
94+
95+
/**
96+
* Initialize the log
97+
*/
98+
public function init_log(): void {
99+
$this->gettext_log = [];
100+
}
101+
102+
/**
103+
* Add translation data to GraphQL extensions
104+
*
105+
* @param \GraphQL\Executor\ExecutionResult $response The GraphQL response
106+
*/
107+
public function add_to_extensions( \GraphQL\Executor\ExecutionResult $response ): \GraphQL\Executor\ExecutionResult {
108+
$extensions = $response->extensions ?? [];
109+
$extensions['translations'] = [
110+
'count' => count( $this->gettext_log ),
111+
// 'log' => $this->gettext_log,
112+
];
113+
$response->extensions = $extensions;
114+
return $response;
115+
}
116+
}
117+
118+
new TestGetText();
119+
\`\`\`
120+
121+
## Does this close any currently open issues?
122+
123+
Working on #3354 (more to come)
124+
125+
## Any other comments?
126+
127+
This change provides significant performance benefits by:
128+
129+
1. **Deferred Translation**: The \`__()\` function calls for field descriptions are now only executed when the fields are actually used in a query, rather than during schema initialization. This is particularly important for multilingual sites where translation lookups can be expensive.
130+
131+
2. **Reduced Memory Usage**: Field definitions that are rarely used in queries no longer need to be stored in memory during the entire request lifecycle.
132+
133+
3. **Faster Schema Initialization**: The schema can be initialized more quickly since field definitions are not processed until they are actually needed.
134+
135+
4. **Better Resource Management**: Resources like database connections or complex calculations needed for field definitions are only allocated when the fields are actually queried.
136+
137+
The changes maintain full backward compatibility while providing these performance improvements. All existing functionality remains the same, but the implementation is now more efficient, especially for large WordPress installations with complex schemas.

.changesets/2025-04-28-pr-3366.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
title: "chore: add array shapes to and "
3+
pr: 3366
4+
author: "justlevine"
5+
type: "chore"
6+
breaking: false
7+
---
8+
9+
## What does this implement/fix? Explain your changes.
10+
11+
This PR fixes the use of \`mixed\` in iterable types inside the \`Admin\Extensions\` and \`Admin\AdminNotices\` class. The only remaining uses of mixed in that class are intentional: i.e. when we're trying to validate if a filtered list of extensions has the necessary data.
12+
13+
Additionally, native types have been implemented in all places in those classes where to do so would not cause any breakings.
14+
15+
There are _no_ breaking or user-facing changes in this PR.
16+
17+
## Does this close any currently open issues?
18+
19+
20+
21+
## Any other comments?

.changesets/2025-04-28-pr-3367.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: "chore: improve type-safety for class"
3+
pr: 3367
4+
author: "justlevine"
5+
type: "chore"
6+
breaking: false
7+
---
8+
9+
## What does this implement/fix? Explain your changes.
10+
11+
This PR:
12+
13+
- Inlines all (backwards-compatible) PHPDoc types into their native PHP types
14+
- Replaces the use of \`mixed\` with the specific array shape (_where possible_)
15+
- Adds type-narrowing to \`WPGraphQL::get_allowed_post_types()\` and \`::get_allowed_taxonomies()\`, so the correct traversable type of the array is hinted correctly.
16+
17+
References to these functions have been cleaned up accordingly (usually just by removing a \`/** @var {...} */\` typehint.
18+
19+
There are _no_ breaking changes in this PR.
20+
21+
22+
## Does this close any currently open issues?
23+
24+
25+
26+
## Any other comments?

.changesets/2025-04-28-pr-3369.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: "fix: don't initialize twice in class constructor"
3+
pr: 3369
4+
author: "justlevine"
5+
type: "fix"
6+
breaking: false
7+
---
8+
9+
## What does this implement/fix? Explain your changes.
10+
11+
This PR fixes a bug in the \`Request::__construct()\` method, where the \`->app_context\` was previously initialized twice.
12+
13+
Now it's only initialized once, while the \`$type_registry\` continues to be injected onto the AppContext class at the same point of the lifecycle.
14+
15+
16+
## Does this close any currently open issues?
17+
18+
19+
20+
## Any other comments?

access-functions.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,12 @@ static function ( \WPGraphQL\Admin\Settings\SettingsRegistry $registry ) use ( $
717717
* @since 0.14.0
718718
*/
719719
function graphql_debug( $message, $config = [] ): void {
720+
721+
// Bail if debug is disabled.
722+
if ( ! WPGraphQL::debug() ) {
723+
return;
724+
}
725+
720726
$debug_backtrace = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace
721727
$config['backtrace'] = ! empty( $debug_backtrace )
722728
?

cli/wp-cli.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ public function generate_static_schema( $args, $assoc_args ) {
6060
// Get the schema
6161
$schema = WPGraphQL::get_schema();
6262

63-
// Reset the introspection query flag
64-
WPGraphQL::set_is_introspection_query( false );
65-
6663
/**
6764
* Format the Schema
6865
*/
@@ -76,6 +73,9 @@ public function generate_static_schema( $args, $assoc_args ) {
7673

7774
file_put_contents( $file_path, $printed ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
7875

76+
// Reset the introspection query flag
77+
WPGraphQL::set_is_introspection_query( false );
78+
7979
/**
8080
* All done!
8181
*/

src/Admin/AdminNotices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public function add_admin_notice( string $slug, array $config ): array {
155155
/**
156156
* Pass the notice through a filter before registering it
157157
*
158-
* @param array<string,mixed> $config The config of the admin notice
158+
* @param AdminNoticeConfig $config The config of the admin notice
159159
* @param string $slug The slug identifying the admin notice
160160
*/
161161
$filtered_notice = apply_filters( 'graphql_add_admin_notice', $config, $slug );

0 commit comments

Comments
 (0)