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

wp-graphql / wp-graphql / 13316763745

13 Feb 2025 08:45PM UTC coverage: 82.712% (-0.3%) from 83.023%
13316763745

push

github

web-flow
Merge pull request #3307 from wp-graphql/release/v2.0.0

release: v2.0.0

195 of 270 new or added lines in 20 files covered. (72.22%)

180 existing lines in 42 files now uncovered.

13836 of 16728 relevant lines covered (82.71%)

299.8 hits per line

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

97.0
/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✔
NEW
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✔
NEW
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✔
NEW
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✔
UNCOV
282
                        return;
×
283
                }
284

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

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

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

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

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

328
                $this->type_registry->register_object_type(
593✔
329
                        $this->connection_name . 'Edge',
593✔
330
                        [
593✔
331
                                'interfaces'  => $interfaces,
593✔
332
                                'description' => sprintf(
593✔
333
                                        // 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
334
                                        __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
593✔
335
                                        $this->from_type,
593✔
336
                                        $this->to_type
593✔
337
                                ),
593✔
338
                                'fields'      => array_merge(
593✔
339
                                        [
593✔
340
                                                'node' => [
593✔
341
                                                        'type'              => [ 'non_null' => $this->to_type ],
593✔
342
                                                        'description'       => __( 'The node of the connection, without the edges', 'wp-graphql' ),
593✔
343
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
344
                                                ],
593✔
345
                                        ],
593✔
346
                                        $this->edge_fields
593✔
347
                                ),
593✔
348
                        ]
593✔
349
                );
593✔
350
        }
351

352
        /**
353
         * Registers the PageInfo type for the connection
354
         *
355
         * @throws \Exception
356
         */
357
        public function register_connection_page_info_type(): void {
593✔
358
                if ( $this->type_registry->has_type( $this->connection_name . 'PageInfo' ) ) {
593✔
359
                        return;
×
360
                }
361

362
                $this->type_registry->register_object_type(
593✔
363
                        $this->connection_name . 'PageInfo',
593✔
364
                        [
593✔
365
                                'interfaces'  => [ $this->to_type . 'ConnectionPageInfo' ],
593✔
366
                                'description' => sprintf(
593✔
367
                                        // translators: %s is the name of the connection.
368
                                        __( 'Page Info on the "%s"', 'wp-graphql' ),
593✔
369
                                        $this->connection_name
593✔
370
                                ),
593✔
371
                                'fields'      => PageInfo::get_fields(),
593✔
372
                        ]
593✔
373
                );
593✔
374
        }
375

376
        /**
377
         * Registers the Connection Edge type to the Schema
378
         *
379
         * @throws \Exception
380
         */
381
        protected function register_connection_edge_type(): void {
593✔
382
                if ( $this->type_registry->has_type( $this->connection_name . 'Edge' ) ) {
593✔
383
                        return;
×
384
                }
385
                // Only include the default interfaces if the user hasnt explicitly opted out.
386
                $default_interfaces = false === $this->include_default_interfaces ? [
593✔
387
                        'Edge',
593✔
388
                ] : [];
593✔
389
                $interfaces         = $this->get_edge_interfaces( $default_interfaces );
593✔
390

391
                $this->type_registry->register_object_type(
593✔
392
                        $this->connection_name . 'Edge',
593✔
393
                        [
593✔
394
                                'description' => __( 'An edge in a connection', 'wp-graphql' ),
593✔
395
                                'interfaces'  => $interfaces,
593✔
396
                                'fields'      => array_merge(
593✔
397
                                        [
593✔
398
                                                'cursor' => [
593✔
399
                                                        'type'              => 'String',
593✔
400
                                                        'description'       => __( 'A cursor for use in pagination', 'wp-graphql' ),
593✔
401
                                                        'resolve'           => $this->resolve_cursor,
593✔
402
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
403
                                                ],
593✔
404
                                                'node'   => [
593✔
405
                                                        'type'              => [ 'non_null' => $this->to_type ],
593✔
406
                                                        'description'       => __( 'The item at the end of the edge', 'wp-graphql' ),
593✔
407
                                                        'deprecationReason' => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
408
                                                ],
593✔
409
                                        ],
593✔
410
                                        $this->edge_fields
593✔
411
                                ),
593✔
412
                        ]
593✔
413
                );
593✔
414
        }
415

416
        /**
417
         * Registers the Connection Type to the Schema
418
         *
419
         * @throws \Exception
420
         */
421
        protected function register_connection_type(): void {
593✔
422
                if ( $this->type_registry->has_type( $this->connection_name ) ) {
593✔
423
                        return;
×
424
                }
425

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

429
                // Only include the default interfaces if the user has not explicitly opted out.
430
                if ( false !== $this->include_default_interfaces ) {
593✔
431
                        $interfaces[] = 'Connection';
593✔
432
                }
433

434
                $this->type_registry->register_object_type(
593✔
435
                        $this->connection_name,
593✔
436
                        [
593✔
437
                                'description'       => sprintf(
593✔
438
                                        // translators: the placeholders are the name of the Types the connection is between.
439
                                        __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
593✔
440
                                        $this->from_type,
593✔
441
                                        $this->to_type
593✔
442
                                ),
593✔
443
                                'interfaces'        => $interfaces,
593✔
444
                                'connection_config' => $this->config,
593✔
445
                                'fields'            => $this->get_connection_fields(),
593✔
446
                        ]
593✔
447
                );
593✔
448
        }
449

450
        /**
451
         * Returns fields to be used on the connection
452
         *
453
         * @return array<string,array<string,mixed>>
454
         */
455
        protected function get_connection_fields(): array {
593✔
456
                return array_merge(
593✔
457
                        [
593✔
458
                                'pageInfo' => [
593✔
459
                                        'type'        => [ 'non_null' => $this->connection_name . 'PageInfo' ],
593✔
460
                                        'description' => __( 'Information about pagination in a connection.', 'wp-graphql' ),
593✔
461
                                ],
593✔
462
                                'edges'    => [
593✔
463
                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->connection_name . 'Edge' ] ] ],
593✔
464
                                        // translators: %s is the name of the connection.
465
                                        'description' => sprintf( __( 'Edges for the %s connection', 'wp-graphql' ), $this->connection_name ),
593✔
466
                                ],
593✔
467
                                'nodes'    => [
593✔
468
                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->to_type ] ] ],
593✔
469
                                        'description' => __( 'The nodes of the connection, without the edges', 'wp-graphql' ),
593✔
470
                                ],
593✔
471
                        ],
593✔
472
                        $this->connection_fields
593✔
473
                );
593✔
474
        }
475

476
        /**
477
         * Get the args used for pagination on connections
478
         *
479
         * @return array<string,array<string,mixed>>
480
         */
481
        protected function get_pagination_args(): array {
593✔
482
                if ( true === $this->one_to_one ) {
593✔
483
                        $pagination_args = [];
593✔
484
                } else {
485
                        $pagination_args = [
593✔
486
                                'first'  => [
593✔
487
                                        'type'        => 'Int',
593✔
488
                                        'description' => __( 'The number of items to return after the referenced "after" cursor', 'wp-graphql' ),
593✔
489
                                ],
593✔
490
                                'last'   => [
593✔
491
                                        'type'        => 'Int',
593✔
492
                                        'description' => __( 'The number of items to return before the referenced "before" cursor', 'wp-graphql' ),
593✔
493
                                ],
593✔
494
                                'after'  => [
593✔
495
                                        'type'        => 'String',
593✔
496
                                        'description' => __( 'Cursor used along with the "first" argument to reference where in the dataset to get data', 'wp-graphql' ),
593✔
497
                                ],
593✔
498
                                'before' => [
593✔
499
                                        'type'        => 'String',
593✔
500
                                        'description' => __( 'Cursor used along with the "last" argument to reference where in the dataset to get data', 'wp-graphql' ),
593✔
501
                                ],
593✔
502
                        ];
593✔
503
                }
504

505
                return $pagination_args;
593✔
506
        }
507

508
        /**
509
         * Registers the connection in the Graph
510
         *
511
         * @throws \Exception
512
         */
513
        public function register_connection_field(): void {
593✔
514

515
                // merge the config so the raw data passed to the connection
516
                // is passed to the field and can be accessed via $info in resolvers
517
                $field_config = array_merge(
593✔
518
                        $this->config,
593✔
519
                        [
593✔
520
                                'type'                  => true === $this->one_to_one ? $this->connection_name . 'Edge' : $this->connection_name,
593✔
521
                                'args'                  => array_merge( $this->get_pagination_args(), $this->where_args ),
593✔
522
                                'auth'                  => $this->auth,
593✔
523
                                'isConnectionField'     => true,
593✔
524
                                'deprecationReason'     => ! empty( $this->config['deprecationReason'] ) ? $this->config['deprecationReason'] : null,
593✔
525
                                'description'           => ! empty( $this->config['description'] )
593✔
526
                                        ? $this->config['description']
593✔
527
                                        : sprintf(
593✔
528
                                                // translators: the placeholders are the name of the Types the connection is between.
529
                                                __( 'Connection between the %1$s type and the %2$s type', 'wp-graphql' ),
593✔
530
                                                $this->from_type,
593✔
531
                                                $this->to_type
593✔
532
                                        ),
593✔
533
                                'resolve'               => function ( $root, $args, $context, $info ) {
593✔
534
                                        $context->connection_query_class = $this->query_class;
402✔
535
                                        $resolve_connection              = $this->resolve_connection;
402✔
536

537
                                        /**
538
                                         * Return the results of the connection resolver
539
                                         */
540
                                        return $resolve_connection( $root, $args, $context, $info );
402✔
541
                                },
593✔
542
                                'allowFieldUnderscores' => isset( $this->config['allowFieldUnderscores'] ) && true === $this->config['allowFieldUnderscores'],
593✔
543
                        ]
593✔
544
                );
593✔
545

546
                $this->type_registry->register_field(
593✔
547
                        $this->from_type,
593✔
548
                        $this->from_field_name,
593✔
549
                        $field_config
593✔
550
                );
593✔
551
        }
552

553
        /**
554
         * @throws \Exception
555
         */
556
        public function register_connection_interfaces(): void {
593✔
557
                $connection_edge_type = Utils::format_type_name( $this->to_type . 'ConnectionEdge' );
593✔
558

559
                if ( ! $this->type_registry->has_type( $this->to_type . 'ConnectionPageInfo' ) ) {
593✔
560
                        $this->type_registry->register_interface_type(
593✔
561
                                $this->to_type . 'ConnectionPageInfo',
593✔
562
                                [
593✔
563
                                        'interfaces'  => [ 'WPPageInfo' ],
593✔
564
                                        // translators: %s is the name of the connection edge.
565
                                        'description' => sprintf( __( 'Page Info on the connected %s', 'wp-graphql' ), $connection_edge_type ),
593✔
566
                                        'fields'      => PageInfo::get_fields(),
593✔
567
                                ]
593✔
568
                        );
593✔
569
                }
570

571
                if ( ! $this->type_registry->has_type( $connection_edge_type ) ) {
593✔
572
                        $this->type_registry->register_interface_type(
593✔
573
                                $connection_edge_type,
593✔
574
                                [
593✔
575
                                        'interfaces'  => [ 'Edge' ],
593✔
576
                                        // translators: %s is the name of the type the connection edge is to.
577
                                        'description' => sprintf( __( 'Edge between a Node and a connected %s', 'wp-graphql' ), $this->to_type ),
593✔
578
                                        'fields'      => [
593✔
579
                                                'node' => [
593✔
580
                                                        'type'        => [ 'non_null' => $this->to_type ],
593✔
581
                                                        // translators: %s is the name of the type the connection edge is to.
582
                                                        'description' => sprintf( __( 'The connected %s Node', 'wp-graphql' ), $this->to_type ),
593✔
583
                                                ],
593✔
584
                                        ],
593✔
585
                                ]
593✔
586
                        );
593✔
587
                }
588

589
                if ( ! $this->one_to_one && ! $this->type_registry->has_type( $this->to_type . 'Connection' ) ) {
593✔
590
                        $this->type_registry->register_interface_type(
593✔
591
                                $this->to_type . 'Connection',
593✔
592
                                [
593✔
593
                                        'interfaces'  => [ 'Connection' ],
593✔
594
                                        // translators: %s is the name of the type the connection is to.
595
                                        'description' => sprintf( __( 'Connection to %s Nodes', 'wp-graphql' ), $this->to_type ),
593✔
596
                                        'fields'      => [
593✔
597
                                                'edges'    => [
593✔
598
                                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $connection_edge_type ] ] ],
593✔
599
                                                        'description' => sprintf(
593✔
600
                                                                // 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.
601
                                                                __( 'A list of edges (relational context) between %1$s and connected %2$s Nodes', 'wp-graphql' ),
593✔
602
                                                                $this->from_type,
593✔
603
                                                                $this->to_type
593✔
604
                                                        ),
593✔
605
                                                ],
593✔
606
                                                'pageInfo' => [
593✔
607
                                                        'type' => [ 'non_null' => $this->to_type . 'ConnectionPageInfo' ],
593✔
608
                                                ],
593✔
609
                                                'nodes'    => [
593✔
610
                                                        'type'        => [ 'non_null' => [ 'list_of' => [ 'non_null' => $this->to_type ] ] ],
593✔
611
                                                        // translators: %s is the name of the type the connection is to.
612
                                                        'description' => sprintf( __( 'A list of connected %s Nodes', 'wp-graphql' ), $this->to_type ),
593✔
613
                                                ],
593✔
614
                                        ],
593✔
615
                                ]
593✔
616
                        );
593✔
617
                }
618
        }
619

620
        /**
621
         * Registers the connection Types and field to the Schema.
622
         *
623
         * @todo change to 'Protected'. This is public for now to allow for backwards compatibility.
624
         *
625
         * @throws \Exception
626
         */
627
        public function register_connection(): void {
593✔
628
                $this->register_connection_input();
593✔
629

630
                if ( false !== $this->include_default_interfaces ) {
593✔
631
                        $this->register_connection_interfaces();
593✔
632
                }
633

634
                if ( true === $this->one_to_one ) {
593✔
635
                        $this->register_one_to_one_connection_edge_type();
593✔
636
                } else {
637
                        $this->register_connection_page_info_type();
593✔
638
                        $this->register_connection_edge_type();
593✔
639
                        $this->register_connection_type();
593✔
640
                }
641

642
                $this->register_connection_field();
593✔
643
        }
644

645
        /**
646
         * Checks whether the connection should be registered to the Schema.
647
         */
648
        protected function should_register(): bool {
593✔
649

650
                // Don't register if the connection has been excluded from the schema.
651
                $excluded_connections = $this->type_registry->get_excluded_connections();
593✔
652
                if ( in_array( strtolower( $this->connection_name ), $excluded_connections, true ) ) {
593✔
653
                        return false;
1✔
654
                }
655

656
                // Don't register if one of the connection types has been excluded from the schema.
657
                $excluded_types = $this->type_registry->get_excluded_types();
593✔
658
                if ( ( in_array( strtolower( $this->from_type ), $excluded_types, true ) || in_array( strtolower( $this->to_type ), $excluded_types, true ) ) ) {
593✔
659
                        return false;
1✔
660
                }
661

662
                return true;
593✔
663
        }
664
}
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