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

wp-graphql / wp-graphql / 14716683875

28 Apr 2025 07:58PM UTC coverage: 84.287% (+1.6%) from 82.648%
14716683875

push

github

actions-user
release: merge develop into master for v2.3.0

15905 of 18870 relevant lines covered (84.29%)

257.23 hits per line

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

97.39
/src/Type/WPConnectionType.php
1
<?php
2
namespace WPGraphQL\Type;
3

4
use GraphQL\Error\UserError;
5
use WPGraphQL\Registry\TypeRegistry;
6
use WPGraphQL\Type\InterfaceType\PageInfo;
7
use WPGraphQL\Utils\Utils;
8

9
/**
10
 * Class WPConnectionType
11
 *
12
 * @package WPGraphQL\Type
13
 */
14
class WPConnectionType {
15

16
        /**
17
         * Configuration for how auth should be handled on the connection field
18
         *
19
         * @var array<string,mixed>
20
         */
21
        protected $auth;
22

23
        /**
24
         * The config for the connection
25
         *
26
         * @var array<string,mixed>
27
         */
28
        protected $config;
29

30
        /**
31
         * The args configured for the connection
32
         *
33
         * @var array<string,array<string,mixed>>
34
         */
35
        protected $connection_args;
36

37
        /**
38
         * The fields to show on the connection
39
         *
40
         * @var array<string,mixed>
41
         */
42
        protected $connection_fields;
43

44
        /**
45
         * @var string[]|null
46
         */
47
        protected $connection_interfaces;
48

49
        /**
50
         * The name of the connection
51
         *
52
         * @var mixed|string
53
         */
54
        protected $connection_name;
55

56
        /**
57
         * The fields to expose on the edge of the connection
58
         *
59
         * @var array<string,array<string,mixed>>
60
         */
61
        protected $edge_fields;
62

63
        /**
64
         * The name of the field the connection will be exposed as
65
         *
66
         * @var string
67
         */
68
        protected $from_field_name;
69

70
        /**
71
         * The name of the GraphQL Type the connection stems from
72
         *
73
         * @var string
74
         */
75
        protected $from_type;
76

77
        /**
78
         * Whether the connection is a one-to-one connection (default is false)
79
         *
80
         * @var bool
81
         */
82
        protected $one_to_one;
83

84
        /**
85
         * The Query Class that is used to resolve the connection.
86
         *
87
         * @var string
88
         */
89
        protected $query_class;
90

91
        /**
92
         * The resolver function to resolve the connection
93
         *
94
         * @var callable(mixed $root,array<string,mixed> $args,\WPGraphQL\AppContext $context,\GraphQL\Type\Definition\ResolveInfo $info):mixed
95
         */
96
        protected $resolve_connection;
97

98
        /**
99
         * @var mixed|null
100
         */
101
        protected $resolve_cursor;
102

103
        /**
104
         * Whether to  include and generate the default GraphQL interfaces on the connection Object types.
105
         *
106
         * @var bool
107
         */
108
        protected $include_default_interfaces;
109

110
        /**
111
         * The name of the GraphQL Type the connection connects to
112
         *
113
         * @var string
114
         */
115
        protected $to_type;
116

117
        /**
118
         * The WPGraphQL TypeRegistry
119
         *
120
         * @var \WPGraphQL\Registry\TypeRegistry
121
         */
122
        protected $type_registry;
123

124
        /**
125
         * The where args for the connection
126
         *
127
         * @var array<string,array<string,mixed>>
128
         */
129
        protected $where_args = [];
130

131
        /**
132
         * WPConnectionType constructor.
133
         *
134
         * @param array<string,mixed>              $config        The config array for the connection
135
         * @param \WPGraphQL\Registry\TypeRegistry $type_registry Instance of the WPGraphQL Type Registry
136
         *
137
         * @throws \Exception
138
         */
139
        public function __construct( array $config, TypeRegistry $type_registry ) {
593✔
140
                $this->type_registry = $type_registry;
593✔
141

142
                /**
143
                 * Filter the config of WPConnectionType
144
                 *
145
                 * @param array<string,mixed>              $config             Array of configuration options passed to the WPConnectionType when instantiating a new type
146
                 * @param \WPGraphQL\Type\WPConnectionType $wp_connection_type The instance of the WPConnectionType class
147
                 */
148
                $config = apply_filters( 'graphql_wp_connection_type_config', $config, $this );
593✔
149

150
                $this->validate_config( $config );
593✔
151

152
                $this->config    = $config;
593✔
153
                $this->from_type = $config['fromType'];
593✔
154
                $this->to_type   = $config['toType'];
593✔
155

156
                /**
157
                 * Filter the connection field name.
158
                 *
159
                 * @internal This filter is internal and used by rename_graphql_field(). It is not intended for use by external code.
160
                 *
161
                 * @param string $from_field_name The name of the field the connection will be exposed as.
162
                 */
163
                $this->from_field_name = apply_filters( "graphql_wp_connection_{$this->from_type}_from_field_name", $config['fromFieldName'] );
593✔
164

165
                $this->connection_name = ! empty( $config['connectionTypeName'] ) ? $config['connectionTypeName'] : $this->get_connection_name( $this->from_type, $this->to_type, $this->from_field_name );
593✔
166

167
                /**
168
                 * Bail if the connection has been de-registered or excluded.
169
                 */
170
                if ( ! $this->should_register() ) {
593✔
171
                        return;
2✔
172
                }
173

174
                $this->auth                       = array_key_exists( 'auth', $config ) && is_array( $config['auth'] ) ? $config['auth'] : [];
593✔
175
                $this->connection_fields          = array_key_exists( 'connectionFields', $config ) && is_array( $config['connectionFields'] ) ? $config['connectionFields'] : [];
593✔
176
                $this->connection_args            = array_key_exists( 'connectionArgs', $config ) && is_array( $config['connectionArgs'] ) ? $config['connectionArgs'] : [];
593✔
177
                $this->edge_fields                = array_key_exists( 'edgeFields', $config ) && is_array( $config['edgeFields'] ) ? $config['edgeFields'] : [];
593✔
178
                $this->resolve_cursor             = array_key_exists( 'resolveCursor', $config ) && is_callable( $config['resolve'] ) ? $config['resolveCursor'] : null;
593✔
179
                $this->resolve_connection         = array_key_exists( 'resolve', $config ) && is_callable( $config['resolve'] ) ? $config['resolve'] : static function () {
593✔
180
                        return null;
3✔
181
                };
593✔
182
                $this->where_args                 = [];
593✔
183
                $this->one_to_one                 = isset( $config['oneToOne'] ) && true === $config['oneToOne'];
593✔
184
                $this->connection_interfaces      = isset( $config['connectionInterfaces'] ) && is_array( $config['connectionInterfaces'] ) ? $config['connectionInterfaces'] : [];
593✔
185
                $this->include_default_interfaces = isset( $config['includeDefaultInterfaces'] ) ? (bool) $config['includeDefaultInterfaces'] : true;
593✔
186
                $this->query_class                = array_key_exists( 'queryClass', $config ) && ! empty( $config['queryClass'] ) ? $config['queryClass'] : null;
593✔
187

188
                /**
189
                 * Run an action when the WPConnectionType is instantiating.
190
                 *
191
                 * @param array<string,mixed>              $config             Array of configuration options passed to the WPObjectType when instantiating a new type
192
                 * @param \WPGraphQL\Type\WPConnectionType $wp_connection_type The instance of the WPConnectionType class
193
                 *
194
                 * @since 1.13.0
195
                 */
196
                do_action( 'graphql_wp_connection_type', $config, $this );
593✔
197

198
                $this->register_connection();
593✔
199
        }
200

201
        /**
202
         * Validates that essential key/value pairs are passed to the connection config.
203
         *
204
         * @param array<string,mixed> $config The config array for the connection.
205
         *
206
         * @throws \GraphQL\Error\UserError If the config is invalid.
207
         */
208
        protected function validate_config( array $config ): void {
593✔
209
                if ( ! array_key_exists( 'fromType', $config ) ) {
593✔
210
                        throw new UserError( esc_html__( 'Connection config needs to have at least a fromType defined', 'wp-graphql' ) );
×
211
                }
212

213
                if ( ! array_key_exists( 'toType', $config ) ) {
593✔
214
                        throw new UserError( esc_html__( 'Connection config needs to have a "toType" defined', 'wp-graphql' ) );
×
215
                }
216

217
                if ( ! array_key_exists( 'fromFieldName', $config ) || ! is_string( $config['fromFieldName'] ) ) {
593✔
218
                        throw new UserError( esc_html__( 'Connection config needs to have "fromFieldName" defined as a string value', 'wp-graphql' ) );
×
219
                }
220
        }
221

222
        /**
223
         * Get edge interfaces
224
         *
225
         * @param string[] $interfaces Array of interfaces to add to the edge.
226
         *
227
         * @return string[]
228
         */
229
        protected function get_edge_interfaces( array $interfaces = [] ): array {
593✔
230

231
                // Only include the default interfaces if the user hasnt explicitly opted out.
232
                if ( false !== $this->include_default_interfaces ) {
593✔
233
                        $interfaces[] = Utils::format_type_name( $this->to_type . 'ConnectionEdge' );
593✔
234
                }
235

236
                if ( ! empty( $this->connection_interfaces ) ) {
593✔
237
                        foreach ( $this->connection_interfaces as $connection_interface ) {
593✔
238
                                $interfaces[] = str_ends_with( $connection_interface, 'Edge' ) ? $connection_interface : $connection_interface . 'Edge';
593✔
239
                        }
240
                }
241
                return $interfaces;
593✔
242
        }
243

244
        /**
245
         * Utility method that formats the connection name given the name of the from Type and the to
246
         * Type
247
         *
248
         * @param string $from_type        Name of the Type the connection is coming from
249
         * @param string $to_type          Name of the Type the connection is going to
250
         * @param string $from_field_name  Acts as an alternative "toType" if connection type already defined using $to_type.
251
         */
252
        public function get_connection_name( string $from_type, string $to_type, string $from_field_name ): string {
593✔
253

254
                // Create connection name using $from_type + To + $to_type + Connection.
255
                $connection_name = ucfirst( $from_type ) . 'To' . ucfirst( $to_type ) . 'Connection';
593✔
256

257
                // If connection type already exists with that connection name. Set connection name using
258
                // $from_field_name + To + $to_type + Connection.
259
                if ( $this->type_registry->has_type( $connection_name ) ) {
593✔
260
                        $connection_name = ucfirst( $from_type ) . 'To' . ucfirst( $from_field_name ) . 'Connection';
593✔
261
                }
262

263
                return $connection_name;
593✔
264
        }
265

266
        /**
267
         * If the connection includes connection args in the config, this registers the input args
268
         * for the connection
269
         *
270
         * @throws \Exception
271
         */
272
        protected function register_connection_input(): void {
593✔
273
                // If there are no connection args, bail
274
                if ( empty( $this->connection_args ) ) {
593✔
275
                        return;
593✔
276
                }
277

278
                $input_fields = $this->connection_args;
593✔
279

280
                // If input fields not array, bail
281
                if ( ! is_array( $input_fields ) ) {
593✔
282
                        return;
×
283
                }
284

285
                $input_name = $this->connection_name . 'WhereArgs';
593✔
286

287
                $this->where_args = [
593✔
288
                        'where' => [
593✔
289
                                'description' => static function () {
593✔
290
                                        return __( 'Arguments for filtering the connection', 'wp-graphql' );
73✔
291
                                },
593✔
292
                                'type'        => $input_name,
593✔
293
                        ],
593✔
294
                ];
593✔
295

296
                // Only register the input type if it hasn't already been registered.
297
                if ( ! $this->type_registry->has_type( $input_name ) ) {
593✔
298
                        $this->type_registry->register_input_type(
593✔
299
                                $input_name,
593✔
300
                                [
593✔
301
                                        'description' => function () {
593✔
302
                                                return sprintf(
23✔
303
                                                        // translators: %s is the name of the connection
304
                                                        __( 'Arguments for filtering the %s connection', 'wp-graphql' ),
23✔
305
                                                        $this->connection_name
23✔
306
                                                );
23✔
307
                                        },
593✔
308
                                        'fields'      => $input_fields,
593✔
309
                                        'queryClass'  => $this->query_class,
593✔
310
                                ]
593✔
311
                        );
593✔
312
                }
313
        }
314

315
        /**
316
         * Registers the One to One Connection Edge type to the Schema
317
         *
318
         * @throws \Exception
319
         */
320
        protected function register_one_to_one_connection_edge_type(): void {
593✔
321
                if ( $this->type_registry->has_type( $this->connection_name . 'Edge' ) ) {
593✔
322
                        return;
×
323
                }
324

325
                // Only include the default interfaces if the user hasnt explicitly opted out.
326
                $default_interfaces = false !== $this->include_default_interfaces ? [
593✔
327
                        'OneToOneConnection',
593✔
328
                        'Edge',
593✔
329
                ] : [];
×
330
                $interfaces         = $this->get_edge_interfaces( $default_interfaces );
593✔
331

332
                $this->type_registry->register_object_type(
593✔
333
                        $this->connection_name . 'Edge',
593✔
334
                        [
593✔
335
                                'interfaces'  => $interfaces,
593✔
336
                                'description' => function () {
593✔
337
                                        return sprintf(
16✔
338
                                                // translators: Placeholders are for the name of the Type the connection is coming from and the name of the Type the connection is going to
339
                                                __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
16✔
340
                                                $this->from_type,
16✔
341
                                                $this->to_type
16✔
342
                                        );
16✔
343
                                },
593✔
344
                                'fields'      => array_merge(
593✔
345
                                        [
593✔
346
                                                'node' => [
593✔
347
                                                        'type'              => [ 'non_null' => $this->to_type ],
593✔
348
                                                        'description'       => static function () {
593✔
349
                                                                return __( 'The node of the connection, without the edges', 'wp-graphql' );
16✔
350
                                                        },
593✔
351
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
352
                                                ],
593✔
353
                                        ],
593✔
354
                                        $this->edge_fields
593✔
355
                                ),
593✔
356
                        ]
593✔
357
                );
593✔
358
        }
359

360
        /**
361
         * Registers the PageInfo type for the connection
362
         *
363
         * @throws \Exception
364
         */
365
        public function register_connection_page_info_type(): void {
593✔
366
                if ( $this->type_registry->has_type( $this->connection_name . 'PageInfo' ) ) {
593✔
367
                        return;
×
368
                }
369

370
                $this->type_registry->register_object_type(
593✔
371
                        $this->connection_name . 'PageInfo',
593✔
372
                        [
593✔
373
                                'interfaces'  => [ $this->to_type . 'ConnectionPageInfo' ],
593✔
374
                                'description' => function () {
593✔
375
                                        return sprintf(
15✔
376
                                                // translators: %s is the name of the connection.
377
                                                __( 'Pagination metadata specific to "%1$s" collections. Provides cursors and flags for navigating through sets of %2$s Nodes.', 'wp-graphql' ),
15✔
378
                                                $this->connection_name,
15✔
379
                                                $this->connection_name
15✔
380
                                        );
15✔
381
                                },
593✔
382
                                'fields'      => PageInfo::get_fields(),
593✔
383
                        ]
593✔
384
                );
593✔
385
        }
386

387
        /**
388
         * Registers the Connection Edge type to the Schema
389
         *
390
         * @throws \Exception
391
         */
392
        protected function register_connection_edge_type(): void {
593✔
393
                if ( $this->type_registry->has_type( $this->connection_name . 'Edge' ) ) {
593✔
394
                        return;
×
395
                }
396
                // Only include the default interfaces if the user hasnt explicitly opted out.
397
                $default_interfaces = false === $this->include_default_interfaces ? [
593✔
398
                        'Edge',
593✔
399
                ] : [];
593✔
400
                $interfaces         = $this->get_edge_interfaces( $default_interfaces );
593✔
401

402
                $this->type_registry->register_object_type(
593✔
403
                        $this->connection_name . 'Edge',
593✔
404
                        [
593✔
405
                                'description' => static function () {
593✔
406
                                        return __( 'An edge in a connection', 'wp-graphql' );
15✔
407
                                },
593✔
408
                                'interfaces'  => $interfaces,
593✔
409
                                'fields'      => array_merge(
593✔
410
                                        [
593✔
411
                                                'cursor' => [
593✔
412
                                                        'type'              => 'String',
593✔
413
                                                        'description'       => static function () {
593✔
414
                                                                return __( 'A cursor for use in pagination', 'wp-graphql' );
15✔
415
                                                        },
593✔
416
                                                        'resolve'           => $this->resolve_cursor,
593✔
417
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
418
                                                ],
593✔
419
                                                'node'   => [
593✔
420
                                                        'type'              => [ 'non_null' => $this->to_type ],
593✔
421
                                                        'description'       => static function () {
593✔
422
                                                                return __( 'The item at the end of the edge', 'wp-graphql' );
15✔
423
                                                        },
593✔
424
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
425
                                                ],
593✔
426
                                        ],
593✔
427
                                        $this->edge_fields
593✔
428
                                ),
593✔
429
                        ]
593✔
430
                );
593✔
431
        }
432

433
        /**
434
         * Registers the Connection Type to the Schema
435
         *
436
         * @throws \Exception
437
         */
438
        protected function register_connection_type(): void {
593✔
439
                if ( $this->type_registry->has_type( $this->connection_name ) ) {
593✔
440
                        return;
×
441
                }
442

443
                $interfaces   = ! empty( $this->connection_interfaces ) ? $this->connection_interfaces : [];
593✔
444
                $interfaces[] = Utils::format_type_name( $this->to_type . 'Connection' );
593✔
445

446
                // Only include the default interfaces if the user has not explicitly opted out.
447
                if ( false !== $this->include_default_interfaces ) {
593✔
448
                        $interfaces[] = 'Connection';
593✔
449
                }
450

451
                $this->type_registry->register_object_type(
593✔
452
                        $this->connection_name,
593✔
453
                        [
593✔
454
                                'description'       => function () {
593✔
455
                                        return sprintf(
19✔
456
                                                // translators: the placeholders are the name of the Types the connection is between.
457
                                                __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
19✔
458
                                                $this->from_type,
19✔
459
                                                $this->to_type
19✔
460
                                        );
19✔
461
                                },
593✔
462
                                'interfaces'        => $interfaces,
593✔
463
                                'connection_config' => $this->config,
593✔
464
                                'fields'            => $this->get_connection_fields(),
593✔
465
                        ]
593✔
466
                );
593✔
467
        }
468

469
        /**
470
         * Returns fields to be used on the connection
471
         *
472
         * @return array<string,array<string,mixed>>
473
         */
474
        protected function get_connection_fields(): array {
593✔
475
                return array_merge(
593✔
476
                        [
593✔
477
                                'pageInfo' => [
593✔
478
                                        'type'        => [ 'non_null' => $this->connection_name . 'PageInfo' ],
593✔
479
                                        'description' => static function () {
593✔
480
                                                return __( 'Information about pagination in a connection.', 'wp-graphql' );
19✔
481
                                        },
593✔
482
                                ],
593✔
483
                                'edges'    => [
593✔
484
                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->connection_name . 'Edge' ] ] ],
593✔
485
                                        'description' => function () {
593✔
486
                                                // translators: %s is the name of the connection.
487
                                                return sprintf( __( 'Edges for the %s connection', 'wp-graphql' ), $this->connection_name );
19✔
488
                                        },
593✔
489
                                ],
593✔
490
                                'nodes'    => [
593✔
491
                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->to_type ] ] ],
593✔
492
                                        'description' => static function () {
593✔
493
                                                return __( 'The nodes of the connection, without the edges', 'wp-graphql' );
19✔
494
                                        },
593✔
495
                                ],
593✔
496
                        ],
593✔
497
                        $this->connection_fields
593✔
498
                );
593✔
499
        }
500

501
        /**
502
         * Get the args used for pagination on connections
503
         *
504
         * @return array<string,array<string,mixed>>
505
         */
506
        protected function get_pagination_args(): array {
593✔
507
                if ( true === $this->one_to_one ) {
593✔
508
                        $pagination_args = [];
593✔
509
                } else {
510
                        $pagination_args = [
593✔
511
                                'first'  => [
593✔
512
                                        'type'        => 'Int',
593✔
513
                                        'description' => static function () {
593✔
514
                                                return __( 'The number of items to return after the referenced "after" cursor', 'wp-graphql' );
73✔
515
                                        },
593✔
516
                                ],
593✔
517
                                'last'   => [
593✔
518
                                        'type'        => 'Int',
593✔
519
                                        'description' => static function () {
593✔
520
                                                return __( 'The number of items to return before the referenced "before" cursor', 'wp-graphql' );
73✔
521
                                        },
593✔
522
                                ],
593✔
523
                                'after'  => [
593✔
524
                                        'type'        => 'String',
593✔
525
                                        'description' => static function () {
593✔
526
                                                return __( 'Cursor used along with the "first" argument to reference where in the dataset to get data', 'wp-graphql' );
73✔
527
                                        },
593✔
528
                                ],
593✔
529
                                'before' => [
593✔
530
                                        'type'        => 'String',
593✔
531
                                        'description' => static function () {
593✔
532
                                                return __( 'Cursor used along with the "last" argument to reference where in the dataset to get data', 'wp-graphql' );
73✔
533
                                        },
593✔
534
                                ],
593✔
535
                        ];
593✔
536
                }
537

538
                return $pagination_args;
593✔
539
        }
540

541
        /**
542
         * Registers the connection in the Graph
543
         *
544
         * @throws \Exception
545
         */
546
        public function register_connection_field(): void {
593✔
547

548
                // merge the config so the raw data passed to the connection
549
                // is passed to the field and can be accessed via $info in resolvers
550
                $field_config = array_merge(
593✔
551
                        $this->config,
593✔
552
                        [
593✔
553
                                'type'                  => true === $this->one_to_one ? $this->connection_name . 'Edge' : $this->connection_name,
593✔
554
                                'args'                  => array_merge( $this->get_pagination_args(), $this->where_args ),
593✔
555
                                'auth'                  => $this->auth,
593✔
556
                                'isConnectionField'     => true,
593✔
557
                                'deprecationReason'     => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
558
                                'description'           => ! empty( $this->config['description'] )
593✔
559
                                        ? $this->config['description']
593✔
560
                                        : sprintf(
593✔
561
                                                // translators: the placeholders are the name of the Types the connection is between.
562
                                                __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
593✔
563
                                                $this->from_type,
593✔
564
                                                $this->to_type
593✔
565
                                        ),
593✔
566
                                'resolve'               => function ( $root, $args, $context, $info ) {
593✔
567
                                        $context->connection_query_class = $this->query_class;
402✔
568
                                        $resolve_connection              = $this->resolve_connection;
402✔
569

570
                                        /**
571
                                         * Return the results of the connection resolver
572
                                         */
573
                                        return $resolve_connection( $root, $args, $context, $info );
402✔
574
                                },
593✔
575
                                'allowFieldUnderscores' => isset( $this->config['allowFieldUnderscores'] ) && true === $this->config['allowFieldUnderscores'],
593✔
576
                        ]
593✔
577
                );
593✔
578

579
                $this->type_registry->register_field(
593✔
580
                        $this->from_type,
593✔
581
                        $this->from_field_name,
593✔
582
                        $field_config
593✔
583
                );
593✔
584
        }
585

586
        /**
587
         * @throws \Exception
588
         */
589
        public function register_connection_interfaces(): void {
593✔
590
                $connection_edge_type = Utils::format_type_name( $this->to_type . 'ConnectionEdge' );
593✔
591

592
                if ( ! $this->type_registry->has_type( $this->to_type . 'ConnectionPageInfo' ) ) {
593✔
593
                        $this->type_registry->register_interface_type(
593✔
594
                                $this->to_type . 'ConnectionPageInfo',
593✔
595
                                [
593✔
596
                                        'interfaces'  => [ 'WPPageInfo' ],
593✔
597
                                        'description' => static function () use ( $connection_edge_type ) {
593✔
598
                                                // translators: %s is the name of the connection edge.
599
                                                return sprintf( __( 'Pagination metadata specific to "%1$s" collections. Provides cursors and flags for navigating through sets of "%2$s" Nodes.', 'wp-graphql' ), $connection_edge_type, $connection_edge_type );
15✔
600
                                        },
593✔
601
                                        'fields'      => PageInfo::get_fields(),
593✔
602
                                ]
593✔
603
                        );
593✔
604
                }
605

606
                if ( ! $this->type_registry->has_type( $connection_edge_type ) ) {
593✔
607
                        $this->type_registry->register_interface_type(
593✔
608
                                $connection_edge_type,
593✔
609
                                [
593✔
610
                                        'interfaces'  => [ 'Edge' ],
593✔
611
                                        'description' => function () {
593✔
612
                                                // translators: %s is the name of the type the connection edge is to.
613
                                                return sprintf( __( 'Represents a connection to a %1$s. Contains both the %2$s Node and metadata about the relationship.', 'wp-graphql' ), $this->to_type, $this->to_type );
26✔
614
                                        },
593✔
615
                                        'fields'      => [
593✔
616
                                                'node' => [
593✔
617
                                                        'type'        => [ 'non_null' => $this->to_type ],
593✔
618
                                                        'description' => function () {
593✔
619
                                                                // translators: %s is the name of the type the connection edge is to.
620
                                                                return sprintf( __( 'The connected %s Node', 'wp-graphql' ), $this->to_type );
26✔
621
                                                        },
593✔
622
                                                ],
593✔
623
                                        ],
593✔
624
                                ]
593✔
625
                        );
593✔
626
                }
627

628
                if ( ! $this->one_to_one && ! $this->type_registry->has_type( $this->to_type . 'Connection' ) ) {
593✔
629
                        $this->type_registry->register_interface_type(
593✔
630
                                $this->to_type . 'Connection',
593✔
631
                                [
593✔
632
                                        'interfaces'  => [ 'Connection' ],
593✔
633
                                        'description' => function () {
593✔
634
                                                // translators: %s is the name of the type the connection is to.
635
                                                return sprintf( __( 'A paginated collection of %1$s Nodes, Supports cursor-based pagination and filtering to efficiently retrieve sets of %2$s Nodes', 'wp-graphql' ), $this->to_type, $this->to_type );
26✔
636
                                        },
593✔
637
                                        'fields'      => [
593✔
638
                                                'edges'    => [
593✔
639
                                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $connection_edge_type ] ] ],
593✔
640
                                                        'description' => function () {
593✔
641
                                                                return sprintf(
26✔
642
                                                                        // translators: %1$s is the name of the type the connection is from, %2$s is the name of the type the connection is to.
643
                                                                        __( 'A list of edges (relational context) between %1$s and connected %2$s Nodes', 'wp-graphql' ),
26✔
644
                                                                        $this->from_type,
26✔
645
                                                                        $this->to_type
26✔
646
                                                                );
26✔
647
                                                        },
593✔
648
                                                ],
593✔
649
                                                'pageInfo' => [
593✔
650
                                                        'type' => [ 'non_null' => $this->to_type . 'ConnectionPageInfo' ],
593✔
651
                                                ],
593✔
652
                                                'nodes'    => [
593✔
653
                                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->to_type ] ] ],
593✔
654
                                                        'description' => function () {
593✔
655
                                                                // translators: %s is the name of the type the connection is to.
656
                                                                return sprintf( __( 'A list of connected %s Nodes', 'wp-graphql' ), $this->to_type );
26✔
657
                                                        },
593✔
658
                                                ],
593✔
659
                                        ],
593✔
660
                                ]
593✔
661
                        );
593✔
662
                }
663
        }
664

665
        /**
666
         * Registers the connection Types and field to the Schema.
667
         *
668
         * @todo change to 'Protected'. This is public for now to allow for backwards compatibility.
669
         *
670
         * @throws \Exception
671
         */
672
        public function register_connection(): void {
593✔
673
                $this->register_connection_input();
593✔
674

675
                if ( false !== $this->include_default_interfaces ) {
593✔
676
                        $this->register_connection_interfaces();
593✔
677
                }
678

679
                if ( true === $this->one_to_one ) {
593✔
680
                        $this->register_one_to_one_connection_edge_type();
593✔
681
                } else {
682
                        $this->register_connection_page_info_type();
593✔
683
                        $this->register_connection_edge_type();
593✔
684
                        $this->register_connection_type();
593✔
685
                }
686

687
                $this->register_connection_field();
593✔
688
        }
689

690
        /**
691
         * Checks whether the connection should be registered to the Schema.
692
         */
693
        protected function should_register(): bool {
593✔
694

695
                // Don't register if the connection has been excluded from the schema.
696
                $excluded_connections = $this->type_registry->get_excluded_connections();
593✔
697
                if ( in_array( strtolower( $this->connection_name ), $excluded_connections, true ) ) {
593✔
698
                        return false;
1✔
699
                }
700

701
                // Don't register if one of the connection types has been excluded from the schema.
702
                $excluded_types = $this->type_registry->get_excluded_types();
593✔
703
                if ( ( in_array( strtolower( $this->from_type ), $excluded_types, true ) || in_array( strtolower( $this->to_type ), $excluded_types, true ) ) ) {
593✔
704
                        return false;
1✔
705
                }
706

707
                return true;
593✔
708
        }
709
}
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

© 2025 Coveralls, Inc