• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wp-graphql / wp-graphql / 17334288077

29 Aug 2025 09:07PM UTC coverage: 84.593% (+0.4%) from 84.169%
17334288077

push

github

actions-user
chore: update changeset for PR #3410

15884 of 18777 relevant lines covered (84.59%)

260.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.32
/src/Data/DataSource.php
1
<?php
2

3
namespace WPGraphQL\Data;
4

5
use GraphQL\Error\UserError;
6
use GraphQL\Type\Definition\ResolveInfo;
7
use GraphQLRelay\Relay;
8
use WPGraphQL\AppContext;
9
use WPGraphQL\Data\Connection\CommentConnectionResolver;
10
use WPGraphQL\Data\Connection\PluginConnectionResolver;
11
use WPGraphQL\Data\Connection\PostObjectConnectionResolver;
12
use WPGraphQL\Data\Connection\TermObjectConnectionResolver;
13
use WPGraphQL\Data\Connection\ThemeConnectionResolver;
14
use WPGraphQL\Data\Connection\UserConnectionResolver;
15
use WPGraphQL\Data\Connection\UserRoleConnectionResolver;
16
use WPGraphQL\Model\Avatar;
17
use WPGraphQL\Model\Comment;
18
use WPGraphQL\Model\CommentAuthor;
19
use WPGraphQL\Model\Menu;
20
use WPGraphQL\Model\Plugin;
21
use WPGraphQL\Model\Post;
22
use WPGraphQL\Model\PostType;
23
use WPGraphQL\Model\Taxonomy;
24
use WPGraphQL\Model\Term;
25
use WPGraphQL\Model\Theme;
26
use WPGraphQL\Model\User;
27
use WPGraphQL\Model\UserRole;
28
use WPGraphQL\Registry\TypeRegistry;
29

30
/**
31
 * Class DataSource
32
 *
33
 * This class serves as a factory for all the resolvers for queries and mutations. This layer of
34
 * abstraction over the actual resolve functions allows easier, granular control over versioning as
35
 * we can change big things behind the scenes if/when needed, and we just need to ensure the
36
 * call to the DataSource method returns the expected data later on. This should make it easy
37
 * down the road to version resolvers if/when changes to the WordPress API are rolled out.
38
 *
39
 * @package WPGraphQL\Data
40
 * @since   0.0.4
41
 */
42
class DataSource {
43

44
        /**
45
         * Stores an array of node definitions
46
         *
47
         * @var mixed[] $node_definition
48
         * @since  0.0.4
49
         */
50
        protected static $node_definition;
51

52

53
        /**
54
         * Retrieves a WP_Comment object for the ID that gets passed
55
         *
56
         * @param int $comment_id The ID of the comment the comment author is associated with.
57
         *
58
         * @return \WPGraphQL\Model\CommentAuthor|null
59
         * @throws \Exception Throws Exception.
60
         */
61
        public static function resolve_comment_author( int $comment_id ) {
×
62
                $comment_author = get_comment( $comment_id );
×
63

64
                return ! empty( $comment_author ) ? new CommentAuthor( $comment_author ) : null;
×
65
        }
66

67
        /**
68
         * Wrapper for the CommentsConnectionResolver class
69
         *
70
         * @param mixed                                $source  The object the connection is coming from
71
         * @param array<string,mixed>                  $args    Query args to pass to the connection resolver
72
         * @param \WPGraphQL\AppContext                $context The context of the query to pass along
73
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
74
         *
75
         * @return \GraphQL\Deferred
76
         * @throws \Exception
77
         * @since 0.0.5
78
         */
79
        public static function resolve_comments_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
17✔
80
                $resolver = new CommentConnectionResolver( $source, $args, $context, $info );
17✔
81

82
                return $resolver->get_connection();
17✔
83
        }
84

85
        /**
86
         * Wrapper for PluginsConnectionResolver::resolve
87
         *
88
         * @param mixed                                $source  The object the connection is coming from
89
         * @param array<string,mixed>                  $args    Array of arguments to pass to resolve method
90
         * @param \WPGraphQL\AppContext                $context AppContext object passed down
91
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
92
         *
93
         * @return \GraphQL\Deferred
94
         * @throws \Exception
95
         * @since  0.0.5
96
         */
97
        public static function resolve_plugins_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
7✔
98
                $resolver = new PluginConnectionResolver( $source, $args, $context, $info );
7✔
99
                return $resolver->get_connection();
7✔
100
        }
101

102
        /**
103
         * Wrapper for PostObjectsConnectionResolver
104
         *
105
         * @param mixed                                $source    The object the connection is coming from
106
         * @param array<string,mixed>                  $args      Arguments to pass to the resolve method
107
         * @param \WPGraphQL\AppContext                $context AppContext object to pass down
108
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
109
         * @param mixed|string|string[]                $post_type Post type of the post we are trying to resolve
110
         *
111
         * @return \GraphQL\Deferred
112
         * @throws \Exception
113
         * @since  0.0.5
114
         */
115
        public static function resolve_post_objects_connection( $source, array $args, AppContext $context, ResolveInfo $info, $post_type ) {
115✔
116
                $resolver = new PostObjectConnectionResolver( $source, $args, $context, $info, $post_type );
115✔
117

118
                return $resolver->get_connection();
115✔
119
        }
120

121
        /**
122
         * Retrieves the taxonomy object for the name of the taxonomy passed
123
         *
124
         * @param string $taxonomy Name of the taxonomy you want to retrieve the taxonomy object for
125
         *
126
         * @return \WPGraphQL\Model\Taxonomy object
127
         * @throws \GraphQL\Error\UserError If no taxonomy is found with the name passed.
128
         * @since  0.0.5
129
         */
130
        public static function resolve_taxonomy( $taxonomy ) {
×
131

132
                /**
133
                 * Get the allowed_taxonomies.
134
                 */
135
                $allowed_taxonomies = \WPGraphQL::get_allowed_taxonomies();
×
136

137
                if ( ! in_array( $taxonomy, $allowed_taxonomies, true ) ) {
×
138
                        // translators: %s is the name of the taxonomy.
139
                        throw new UserError( esc_html( sprintf( __( 'No taxonomy was found with the name %s', 'wp-graphql' ), $taxonomy ) ) );
×
140
                }
141

142
                $tax_object = get_taxonomy( $taxonomy );
×
143

144
                if ( ! $tax_object instanceof \WP_Taxonomy ) {
×
145
                        // translators: %s is the name of the taxonomy.
146
                        throw new UserError( esc_html( sprintf( __( 'No taxonomy was found with the name %s', 'wp-graphql' ), $taxonomy ) ) );
×
147
                }
148

149
                return new Taxonomy( $tax_object );
×
150
        }
151

152
        /**
153
         * Wrapper for TermObjectConnectionResolver::resolve
154
         *
155
         * @param mixed                                $source   The object the connection is coming from
156
         * @param array<string,mixed>                  $args     Array of args to be passed to the resolve method
157
         * @param \WPGraphQL\AppContext                $context The AppContext object to be passed down
158
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
159
         * @param string                               $taxonomy The name of the taxonomy the term belongs to
160
         *
161
         * @return \GraphQL\Deferred
162
         * @throws \Exception
163
         * @since  0.0.5
164
         */
165
        public static function resolve_term_objects_connection( $source, array $args, AppContext $context, ResolveInfo $info, string $taxonomy ) {
27✔
166
                $resolver = new TermObjectConnectionResolver( $source, $args, $context, $info, $taxonomy );
27✔
167

168
                return $resolver->get_connection();
27✔
169
        }
170

171
        /**
172
         * Retrieves the theme object for the theme you are looking for
173
         *
174
         * @param string $stylesheet Directory name for the theme.
175
         *
176
         * @return \WPGraphQL\Model\Theme object
177
         * @throws \GraphQL\Error\UserError
178
         * @since  0.0.5
179
         */
180
        public static function resolve_theme( $stylesheet ) {
2✔
181
                $theme = wp_get_theme( $stylesheet );
2✔
182
                if ( $theme->exists() ) {
2✔
183
                        return new Theme( $theme );
1✔
184
                } else {
185
                        // translators: %s is the name of the theme stylesheet.
186
                        throw new UserError( esc_html( sprintf( __( 'No theme was found with the stylesheet: %s', 'wp-graphql' ), $stylesheet ) ) );
1✔
187
                }
188
        }
189

190
        /**
191
         * Wrapper for the ThemesConnectionResolver::resolve method
192
         *
193
         * @param mixed                                $source  The object the connection is coming from
194
         * @param array<string,mixed>                  $args    Passes an array of arguments to the resolve method
195
         * @param \WPGraphQL\AppContext                $context The AppContext object to be passed down
196
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
197
         *
198
         * @return \GraphQL\Deferred
199
         * @throws \Exception
200
         * @since  0.0.5
201
         */
202
        public static function resolve_themes_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
×
203
                $resolver = new ThemeConnectionResolver( $source, $args, $context, $info );
×
204
                return $resolver->get_connection();
×
205
        }
206

207
        /**
208
         * Wrapper for the UsersConnectionResolver::resolve method
209
         *
210
         * @param mixed                                $source  The object the connection is coming from
211
         * @param array<string,mixed>                  $args    Array of args to be passed down to the resolve method
212
         * @param \WPGraphQL\AppContext                $context The AppContext object to be passed down
213
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
214
         *
215
         * @return \GraphQL\Deferred
216
         * @throws \Exception
217
         * @since  0.0.5
218
         */
219
        public static function resolve_users_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
52✔
220
                $resolver = new UserConnectionResolver( $source, $args, $context, $info );
52✔
221

222
                return $resolver->get_connection();
49✔
223
        }
224

225
        /**
226
         * Returns an array of data about the user role you are requesting
227
         *
228
         * @param string $name Name of the user role you want info for
229
         *
230
         * @return \WPGraphQL\Model\UserRole
231
         * @throws \GraphQL\Error\UserError If no user role is found with the name passed.
232
         * @since  0.0.30
233
         */
234
        public static function resolve_user_role( $name ) {
2✔
235
                $role = isset( wp_roles()->roles[ $name ] ) ? wp_roles()->roles[ $name ] : null;
2✔
236

237
                if ( null === $role ) {
2✔
238
                        // translators: %s is the name of the user role.
239
                        throw new UserError( esc_html( sprintf( __( 'No user role was found with the name %s', 'wp-graphql' ), $name ) ) );
1✔
240
                } else {
241
                        $role                = (array) $role;
1✔
242
                        $role['id']          = $name;
1✔
243
                        $role['displayName'] = $role['name'];
1✔
244
                        $role['name']        = $name;
1✔
245

246
                        return new UserRole( $role );
1✔
247
                }
248
        }
249

250
        /**
251
         * Resolve the avatar for a user
252
         *
253
         * @param int                 $user_id ID of the user to get the avatar data for
254
         * @param array<string,mixed> $args    The args to pass to the get_avatar_data function
255
         *
256
         * @return \WPGraphQL\Model\Avatar|null
257
         * @throws \Exception
258
         */
259
        public static function resolve_avatar( int $user_id, array $args ) {
6✔
260
                $avatar = get_avatar_data( absint( $user_id ), $args );
6✔
261

262
                // if there's no url returned, return null
263
                if ( empty( $avatar['url'] ) ) {
6✔
264
                        return null;
×
265
                }
266

267
                $avatar = new Avatar( $avatar );
6✔
268

269
                if ( 'private' === $avatar->get_visibility() ) {
6✔
270
                        return null;
1✔
271
                }
272

273
                return $avatar;
6✔
274
        }
275

276
        /**
277
         * Resolve the connection data for user roles
278
         *
279
         * @param mixed[]                              $source  The Query results
280
         * @param array<string,mixed>                  $args    The query arguments
281
         * @param \WPGraphQL\AppContext                $context The AppContext passed down to the query
282
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
283
         *
284
         * @return \GraphQL\Deferred
285
         * @throws \Exception
286
         */
287
        public static function resolve_user_role_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
×
288
                $resolver = new UserRoleConnectionResolver( $source, $args, $context, $info );
×
289

290
                return $resolver->get_connection();
×
291
        }
292

293
        /**
294
         * Format the setting group name to our standard.
295
         *
296
         * @param string $group
297
         *
298
         * @return string $group
299
         */
300
        public static function format_group_name( string $group ) {
601✔
301
                $replaced_group = graphql_format_name( $group, ' ', '/[^a-zA-Z0-9 -]/' );
601✔
302

303
                if ( ! empty( $replaced_group ) ) {
601✔
304
                        $group = $replaced_group;
601✔
305
                }
306

307
                $group = lcfirst( str_replace( '_', ' ', ucwords( $group, '_' ) ) );
601✔
308
                $group = lcfirst( str_replace( '-', ' ', ucwords( $group, '_' ) ) );
601✔
309
                $group = lcfirst( str_replace( ' ', '', ucwords( $group, ' ' ) ) );
601✔
310

311
                return $group;
601✔
312
        }
313

314
        /**
315
         * Get all of the allowed settings by group and return the
316
         * settings group that matches the group param
317
         *
318
         * @param string                           $group
319
         * @param \WPGraphQL\Registry\TypeRegistry $type_registry The WPGraphQL TypeRegistry
320
         *
321
         * @return array<string,mixed>
322
         */
323
        public static function get_setting_group_fields( string $group, TypeRegistry $type_registry ) {
601✔
324

325
                /**
326
                 * Get all of the settings, sorted by group
327
                 */
328
                $settings_groups = self::get_allowed_settings_by_group( $type_registry );
601✔
329

330
                return ! empty( $settings_groups[ $group ] ) ? $settings_groups[ $group ] : [];
601✔
331
        }
332

333
        /**
334
         * Get all of the allowed settings by group
335
         *
336
         * @param \WPGraphQL\Registry\TypeRegistry $type_registry The WPGraphQL TypeRegistry
337
         *
338
         * @return array<string,array<string,mixed>> $allowed_settings_by_group
339
         */
340
        public static function get_allowed_settings_by_group( TypeRegistry $type_registry ) {
601✔
341

342
                /**
343
                 * Get all registered settings
344
                 */
345
                $registered_settings = get_registered_settings();
601✔
346

347
                /**
348
                 * Loop through the $registered_settings array and build an array of
349
                 * settings for each group ( general, reading, discussion, writing, reading, etc. )
350
                 * if the setting is allowed in REST or GraphQL
351
                 */
352
                $allowed_settings_by_group = [];
601✔
353
                foreach ( $registered_settings as $key => $setting ) {
601✔
354
                        // Bail if the setting doesn't have a group.
355
                        if ( empty( $setting['group'] ) ) {
601✔
356
                                continue;
×
357
                        }
358

359
                        $group = self::format_group_name( $setting['group'] );
601✔
360

361
                        if ( ! isset( $setting['type'] ) || ! $type_registry->get_type( $setting['type'] ) ) {
601✔
362
                                continue;
×
363
                        }
364

365
                        if ( ! isset( $setting['show_in_graphql'] ) ) {
601✔
366
                                if ( isset( $setting['show_in_rest'] ) && false !== $setting['show_in_rest'] ) {
601✔
367
                                        $setting['key']                              = $key;
601✔
368
                                        $allowed_settings_by_group[ $group ][ $key ] = $setting;
601✔
369
                                }
370
                        } elseif ( true === $setting['show_in_graphql'] ) {
116✔
371
                                $setting['key']                              = $key;
116✔
372
                                $allowed_settings_by_group[ $group ][ $key ] = $setting;
116✔
373
                        }
374
                }
375

376
                /**
377
                 * Set the setting groups that are allowed
378
                 */
379
                $allowed_settings_by_group = ! empty( $allowed_settings_by_group ) ? $allowed_settings_by_group : [];
601✔
380

381
                /**
382
                 * Filter the $allowed_settings_by_group to allow enabling or disabling groups in the GraphQL Schema.
383
                 *
384
                 * @param array<string,array<string,mixed>> $allowed_settings_by_group
385
                 */
386
                return apply_filters( 'graphql_allowed_settings_by_group', $allowed_settings_by_group );
601✔
387
        }
388

389
        /**
390
         * Get all of the $allowed_settings
391
         *
392
         * @param \WPGraphQL\Registry\TypeRegistry $type_registry The WPGraphQL TypeRegistry
393
         *
394
         * @return array<string,array<string,mixed>> $allowed_settings
395
         */
396
        public static function get_allowed_settings( TypeRegistry $type_registry ) {
601✔
397

398
                /**
399
                 * Get all registered settings
400
                 */
401
                $registered_settings = get_registered_settings();
601✔
402

403
                /**
404
                 * Set allowed settings variable.
405
                 */
406
                $allowed_settings = [];
601✔
407

408
                if ( ! empty( $registered_settings ) ) {
601✔
409

410
                        /**
411
                         * Loop through the $registered_settings and if the setting is allowed in REST or GraphQL
412
                         * add it to the $allowed_settings array
413
                         */
414
                        foreach ( $registered_settings as $key => $setting ) {
601✔
415
                                if ( ! isset( $setting['type'] ) || ! $type_registry->get_type( $setting['type'] ) ) {
601✔
416
                                        continue;
×
417
                                }
418

419
                                if ( ! isset( $setting['show_in_graphql'] ) ) {
601✔
420
                                        if ( isset( $setting['show_in_rest'] ) && false !== $setting['show_in_rest'] ) {
601✔
421
                                                $setting['key']           = $key;
601✔
422
                                                $allowed_settings[ $key ] = $setting;
601✔
423
                                        }
424
                                } elseif ( true === $setting['show_in_graphql'] ) {
116✔
425
                                        $setting['key']           = $key;
116✔
426
                                        $allowed_settings[ $key ] = $setting;
116✔
427
                                }
428
                        }
429
                }
430

431
                /**
432
                 * Verify that we have the allowed settings
433
                 */
434
                $allowed_settings = ! empty( $allowed_settings ) ? $allowed_settings : [];
601✔
435

436
                /**
437
                 * Filter the $allowed_settings to allow some to be enabled or disabled from showing in
438
                 * the GraphQL Schema.
439
                 *
440
                 * @param array<string,array<string,mixed>> $allowed_settings
441
                 */
442
                return apply_filters( 'graphql_allowed_setting_groups', $allowed_settings );
601✔
443
        }
444

445
        /**
446
         * We get the node interface and field from the relay library.
447
         *
448
         * The first method is the way we resolve an ID to its object. The second is the way we resolve
449
         * an object that implements node to its type.
450
         *
451
         * @return mixed[]
452
         * @throws \GraphQL\Error\UserError
453
         */
454
        public static function get_node_definition() {
×
455
                if ( null === self::$node_definition ) {
×
456
                        $node_definition = Relay::nodeDefinitions(
×
457
                        // The ID fetcher definition
458
                                static function ( $global_id, AppContext $context, ResolveInfo $info ) {
×
459
                                        self::resolve_node( $global_id, $context, $info );
×
460
                                },
×
461
                                // Type resolver
462
                                static function ( $node ) {
×
463
                                        self::resolve_node_type( $node );
×
464
                                }
×
465
                        );
×
466

467
                        self::$node_definition = $node_definition;
×
468
                }
469

470
                return self::$node_definition;
×
471
        }
472

473
        /**
474
         * Given a node, returns the GraphQL Type
475
         *
476
         * @param mixed $node The node to resolve the type of
477
         *
478
         * @return string
479
         * @throws \GraphQL\Error\UserError If no type is found for the node.
480
         */
481
        public static function resolve_node_type( $node ) {
13✔
482
                $type = null;
13✔
483

484
                if ( true === is_object( $node ) ) {
13✔
485
                        switch ( true ) {
486
                                case $node instanceof Post:
13✔
487
                                        if ( $node->isRevision ) {
4✔
488
                                                /** @var ?\WP_Post */
489
                                                $parent_post = get_post( $node->parentDatabaseId );
×
490

491
                                                if ( ! empty( $parent_post ) ) {
×
492
                                                        /** @var \WP_Post_Type $post_type_object */
493
                                                        $post_type_object = get_post_type_object( $parent_post->post_type );
×
494
                                                        $type             = $post_type_object->graphql_single_name ?? null;
×
495

496
                                                        break;
×
497
                                                }
498
                                        }
499

500
                                        /** @var \WP_Post_Type $post_type_object */
501
                                        $post_type_object = isset( $node->post_type ) ? get_post_type_object( $node->post_type ) : null;
4✔
502
                                        $type             = $post_type_object->graphql_single_name ?? null;
4✔
503
                                        break;
4✔
504
                                case $node instanceof Term:
9✔
505
                                        /** @var \WP_Taxonomy $tax_object */
506
                                        $tax_object = isset( $node->taxonomyName ) ? get_taxonomy( $node->taxonomyName ) : null;
×
507
                                        $type       = $tax_object->graphql_single_name;
×
508
                                        break;
×
509
                                case $node instanceof Comment:
9✔
510
                                        $type = 'Comment';
1✔
511
                                        break;
1✔
512
                                case $node instanceof PostType:
8✔
513
                                        $type = 'ContentType';
1✔
514
                                        break;
1✔
515
                                case $node instanceof Taxonomy:
7✔
516
                                        $type = 'Taxonomy';
1✔
517
                                        break;
1✔
518
                                case $node instanceof Theme:
6✔
519
                                        $type = 'Theme';
1✔
520
                                        break;
1✔
521
                                case $node instanceof User:
5✔
522
                                        $type = 'User';
3✔
523
                                        break;
3✔
524
                                case $node instanceof Plugin:
2✔
525
                                        $type = 'Plugin';
1✔
526
                                        break;
1✔
527
                                case $node instanceof CommentAuthor:
1✔
528
                                        $type = 'CommentAuthor';
1✔
529
                                        break;
1✔
530
                                case $node instanceof Menu:
×
531
                                        $type = 'Menu';
×
532
                                        break;
×
533
                                case $node instanceof \_WP_Dependency:
×
534
                                        $type = isset( $node->type ) ? $node->type : null;
×
535
                                        break;
×
536
                                default:
537
                                        $type = null;
×
538
                        }
539
                }
540

541
                /**
542
                 * Add a filter to allow externally registered node types to return the proper type
543
                 * based on the node_object that's returned
544
                 *
545
                 * @param mixed|object|array $type The type definition the node should resolve to.
546
                 * @param mixed|object|array $node The $node that is being resolved
547
                 *
548
                 * @since 0.0.6
549
                 */
550
                $type = apply_filters( 'graphql_resolve_node_type', $type, $node );
13✔
551

552
                /**
553
                 * If the $type is not properly resolved, throw an exception
554
                 *
555
                 * @since 0.0.6
556
                 */
557
                if ( empty( $type ) ) {
13✔
558
                        throw new UserError( esc_html__( 'No type was found matching the node', 'wp-graphql' ) );
×
559
                }
560

561
                /**
562
                 * Return the resolved $type for the $node
563
                 *
564
                 * @since 0.0.5
565
                 */
566
                return ucfirst( $type );
13✔
567
        }
568

569
        /**
570
         * Given the ID of a node, this resolves the data
571
         *
572
         * @param string                               $global_id The Global ID of the node
573
         * @param \WPGraphQL\AppContext                $context The Context of the GraphQL Request
574
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo for the GraphQL Request
575
         *
576
         * @return ?\GraphQL\Deferred
577
         * @throws \GraphQL\Error\UserError If no ID is passed.
578
         */
579
        public static function resolve_node( $global_id, AppContext $context, ResolveInfo $info ) {
17✔
580
                if ( empty( $global_id ) ) {
17✔
581
                        throw new UserError( esc_html__( 'An ID needs to be provided to resolve a node.', 'wp-graphql' ) );
×
582
                }
583

584
                /**
585
                 * Convert the encoded ID into an array we can work with
586
                 *
587
                 * @since 0.0.4
588
                 */
589
                $id_components = Relay::fromGlobalId( $global_id );
17✔
590

591
                /**
592
                 * $id_components is an array with the id and type
593
                 *
594
                 * @since 0.0.5
595
                 */
596
                if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
17✔
597
                        // translators: %s is the global ID.
598
                        throw new UserError( esc_html( sprintf( __( 'The global ID isn\'t recognized ID: %s', 'wp-graphql' ), $global_id ) ) );
1✔
599
                }
600

601
                /**
602
                 * Get the allowed_post_types and allowed_taxonomies
603
                 *
604
                 * @since 0.0.5
605
                 */
606

607
                $loader = $context->get_loader( $id_components['type'] );
16✔
608

609
                if ( $loader ) {
16✔
610
                        return $loader->load_deferred( $id_components['id'] );
16✔
611
                }
612

613
                return null;
×
614
        }
615

616
        /**
617
         * Returns array of nav menu location names
618
         *
619
         * @return string[]
620
         */
621
        public static function get_registered_nav_menu_locations() {
601✔
622
                global $_wp_registered_nav_menus;
601✔
623

624
                return ! empty( $_wp_registered_nav_menus ) && is_array( $_wp_registered_nav_menus ) ? array_keys( $_wp_registered_nav_menus ) : [];
601✔
625
        }
626

627
        /**
628
         * This resolves a resource, given a URI (the path / permalink to a resource)
629
         *
630
         * Based largely on the core parse_request function in wp-includes/class-wp.php
631
         *
632
         * @param string                               $uri     The URI to fetch a resource from
633
         * @param \WPGraphQL\AppContext                $context The AppContext passed through the GraphQL Resolve Tree
634
         * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed through the GraphQL Resolve tree
635
         *
636
         * @return \GraphQL\Deferred
637
         * @throws \Exception
638
         */
639
        public static function resolve_resource_by_uri( $uri, $context, $info ) {
×
640
                $node_resolver = new NodeResolver( $context );
×
641

642
                return $node_resolver->resolve_uri( $uri );
×
643
        }
644

645
        /**
646
         * @todo remove in 3.0.0
647
         * @deprecated Use the Loader passed in $context instead
648
         * @codeCoverageIgnore
649
         *
650
         * @param int                   $id      ID of the comment we want to get the object for.
651
         * @param \WPGraphQL\AppContext $context The context of the request.
652
         *
653
         * @return \GraphQL\Deferred object
654
         * @throws \GraphQL\Error\UserError Throws UserError.
655
         * @throws \Exception Throws UserError.
656
         */
657
        public static function resolve_comment( $id, $context ) {
658
                _doing_it_wrong(
659
                        __METHOD__,
660
                        sprintf(
661
                                /* translators: %s is the method name */
662
                                esc_html__( 'This method will be removed in the next major release. Use %s instead.', 'wp-graphql' ),
663
                                '$context->get_loader( \'comment\' )->load_deferred( $id )'
664
                        ),
665
                        '0.8.4'
666
                );
667

668
                return $context->get_loader( 'comment' )->load_deferred( $id );
669
        }
670

671
        /**
672
         * @todo remove in 3.0.0
673
         * @deprecated Use the Loader passed in $context instead
674
         * @codeCoverageIgnore
675
         *
676
         * @param int                   $id      ID of the post you are trying to retrieve
677
         * @param \WPGraphQL\AppContext $context The context of the GraphQL Request
678
         *
679
         * @return \GraphQL\Deferred
680
         *
681
         * @throws \GraphQL\Error\UserError
682
         * @throws \Exception
683
         */
684
        public static function resolve_post_object( int $id, AppContext $context ) {
685
                _doing_it_wrong(
686
                        __METHOD__,
687
                        sprintf(
688
                                /* translators: %s is the method name */
689
                                esc_html__( 'This method will be removed in the next major release. Use %s instead.', 'wp-graphql' ),
690
                                '$context->get_loader( \'post\' )->load_deferred( $id )'
691
                        ),
692
                        '0.8.4'
693
                );
694
                return $context->get_loader( 'post' )->load_deferred( $id );
695
        }
696

697
        /**
698
         * @todo remove in 3.0.0
699
         * @deprecated Use the Loader passed in $context instead
700
         * @codeCoverageIgnore
701
         *
702
         * @param int                   $id      The ID of the menu item to load
703
         * @param \WPGraphQL\AppContext $context The context of the GraphQL request
704
         *
705
         * @return \GraphQL\Deferred|null
706
         * @throws \Exception
707
         */
708
        public static function resolve_menu_item( int $id, AppContext $context ) {
709
                _doing_it_wrong(
710
                        __METHOD__,
711
                        sprintf(
712
                                /* translators: %s is the method name */
713
                                esc_html__( 'This method will be removed in the next major release. Use %s instead.', 'wp-graphql' ),
714
                                '$context->get_loader( \'menu_item\' )->load_deferred( $id )'
715
                        ),
716
                        '0.8.4'
717
                );
718
                return $context->get_loader( 'post' )->load_deferred( $id );
719
        }
720

721
        /**
722
         * @todo remove in 3.0.0
723
         * @deprecated Use the Loader passed in $context instead
724
         * @codeCoverageIgnore
725
         *
726
         * @param int                   $id      ID of the term you are trying to retrieve the object for
727
         * @param \WPGraphQL\AppContext $context The context of the GraphQL Request
728
         *
729
         * @return \GraphQL\Deferred
730
         * @throws \Exception
731
         */
732
        public static function resolve_term_object( $id, AppContext $context ) {
733
                _doing_it_wrong(
734
                        __METHOD__,
735
                        sprintf(
736
                                /* translators: %s is the method name */
737
                                esc_html__( 'This method will be removed in the next major release. Use %s instead.', 'wp-graphql' ),
738
                                '$context->get_loader( \'term\' )->load_deferred( $id )'
739
                        ),
740
                        '0.8.4'
741
                );
742
                return $context->get_loader( 'term' )->load_deferred( $id );
743
        }
744

745
        /**
746
         * @todo remove in 3.0.0
747
         * @deprecated Use the Loader passed in $context instead
748
         * @codeCoverageIgnore
749
         *
750
         * @param int                   $id      ID of the user you want the object for
751
         * @param \WPGraphQL\AppContext $context The AppContext
752
         *
753
         * @return \GraphQL\Deferred
754
         * @throws \Exception
755
         */
756
        public static function resolve_user( $id, AppContext $context ) {
757
                _doing_it_wrong(
758
                        __METHOD__,
759
                        sprintf(
760
                                /* translators: %s is the method name */
761
                                esc_html__( 'This method will be removed in the next major release. Use %s instead.', 'wp-graphql' ),
762
                                '$context->get_loader( \'user\' )->load_deferred( $id )'
763
                        ),
764
                        '0.8.4'
765
                );
766
                return $context->get_loader( 'user' )->load_deferred( $id );
767
        }
768
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc