• 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

96.5
/src/Registry/Utils/PostObject.php
1
<?php
2

3
namespace WPGraphQL\Registry\Utils;
4

5
use GraphQL\Type\Definition\ResolveInfo;
6
use WPGraphQL;
7
use WPGraphQL\AppContext;
8
use WPGraphQL\Data\Connection\CommentConnectionResolver;
9
use WPGraphQL\Data\Connection\PostObjectConnectionResolver;
10
use WPGraphQL\Data\Connection\TermObjectConnectionResolver;
11
use WPGraphQL\Model\Post;
12
use WPGraphQL\Type\Connection\Comments;
13
use WPGraphQL\Type\Connection\PostObjects;
14
use WPGraphQL\Type\Connection\TermObjects;
15
use WP_Post_Type;
16

17
/**
18
 * Class PostObject
19
 *
20
 * @package WPGraphQL\Data
21
 * @since   1.12.0
22
 */
23
class PostObject {
24

25
        /**
26
         * Registers a post_type type to the schema as either a GraphQL object, interface, or union.
27
         *
28
         * @param \WP_Post_Type $post_type_object Post type.
29
         *
30
         * @return void
31
         * @throws \Exception
32
         */
33
        public static function register_types( WP_Post_Type $post_type_object ) {
593✔
34
                $single_name = $post_type_object->graphql_single_name;
593✔
35

36
                $config = [
593✔
37
                        'description' => static function () use ( $post_type_object, $single_name ) {
593✔
38
                                return ! empty( $post_type_object->graphql_description )
20✔
39
                                        ? $post_type_object->graphql_description
19✔
40
                                        : ( ! empty( $post_type_object->description )
8✔
41
                                                ? $post_type_object->description
×
42
                                        /* translators: post object singular name w/ description */
8✔
43
                                                : sprintf( __( 'The %s type', 'wp-graphql' ), $single_name )
20✔
44
                                        );
20✔
45
                        },
593✔
46
                        'connections' => static::get_connections( $post_type_object ),
593✔
47
                        'interfaces'  => static::get_interfaces( $post_type_object ),
593✔
48
                        'fields'      => static::get_fields( $post_type_object ),
593✔
49
                        'model'       => Post::class,
593✔
50
                ];
593✔
51

52
                // Register as GraphQL objects.
53
                if ( 'object' === $post_type_object->graphql_kind ) {
593✔
54
                        register_graphql_object_type( $single_name, $config );
593✔
55

56
                        // Register fields to the Type used for attachments (MediaItem)
57
                        if ( 'attachment' === $post_type_object->name && true === $post_type_object->show_in_graphql && isset( $post_type_object->graphql_single_name ) ) {
593✔
58
                                self::register_attachment_fields( $post_type_object );
592✔
59
                        }
60

61
                        return;
593✔
62
                }
63

64
                /**
65
                 * Register as GraphQL interfaces or unions.
66
                 *
67
                 * It's assumed that the types used in `resolveType` have already been registered to the schema.
68
                 */
69

70
                // Bail early if graphql_resolve_type isnt a vallable callback.
71
                if ( empty( $post_type_object->graphql_resolve_type ) || ! is_callable( $post_type_object->graphql_resolve_type ) ) {
3✔
72
                        graphql_debug(
1✔
73
                                sprintf(
1✔
74
                                        // translators: %1$s is the post type name, %2$s is the graphql kind.
75
                                        __( '%1$s is registered as a GraphQL %2$s, but has no way to resolve the type. Ensure "graphql_resolve_type" is a valid callback function', 'wp-graphql' ),
1✔
76
                                        $single_name,
1✔
77
                                        $post_type_object->graphql_kind
1✔
78
                                ),
1✔
79
                                [ 'registered_post_type_object' => $post_type_object ]
1✔
80
                        );
1✔
81

82
                        return;
1✔
83
                }
84

85
                $config['resolveType'] = $post_type_object->graphql_resolve_type;
3✔
86

87
                if ( 'interface' === $post_type_object->graphql_kind ) {
3✔
88
                        register_graphql_interface_type( $single_name, $config );
1✔
89

90
                        return;
1✔
91
                } elseif ( 'union' === $post_type_object->graphql_kind ) {
2✔
92

93
                        // Bail early if graphql_union_types is not defined.
94
                        if ( empty( $post_type_object->graphql_union_types ) || ! is_array( $post_type_object->graphql_union_types ) ) {
2✔
95
                                graphql_debug(
1✔
96
                                        __( 'Registering a post type with "graphql_kind" => "union" requires "graphql_union_types" to be a valid array of possible GraphQL type names.', 'wp-graphql' ),
1✔
97
                                        [ 'registered_post_type_object' => $post_type_object ]
1✔
98
                                );
1✔
99

100
                                return;
1✔
101
                        }
102

103
                        // Set the possible types for the union.
104
                        $config['typeNames'] = $post_type_object->graphql_union_types;
1✔
105

106
                        register_graphql_union_type( $single_name, $config );
1✔
107
                }
108
        }
109

110
        /**
111
         * Gets all the connections for the given post type.
112
         *
113
         * @param \WP_Post_Type $post_type_object
114
         *
115
         * @return array<string,array<string,mixed>>
116
         */
117
        protected static function get_connections( WP_Post_Type $post_type_object ) {
593✔
118
                $connections = [];
593✔
119

120
                // Comments.
121
                if ( post_type_supports( $post_type_object->name, 'comments' ) ) {
593✔
122
                        $connections['comments'] = [
593✔
123
                                'toType'         => 'Comment',
593✔
124
                                'connectionArgs' => Comments::get_connection_args(),
593✔
125
                                'resolve'        => static function ( Post $post, $args, $context, $info ) {
593✔
126
                                        if ( $post->isRevision ) {
3✔
127
                                                $id = $post->parentDatabaseId;
×
128
                                        } else {
129
                                                $id = $post->databaseId;
3✔
130
                                        }
131

132
                                        $resolver = new CommentConnectionResolver( $post, $args, $context, $info );
3✔
133

134
                                        return $resolver->set_query_arg( 'post_id', absint( $id ) )->get_connection();
3✔
135
                                },
593✔
136
                        ];
593✔
137
                }
138

139
                // Previews.
140
                if ( ! in_array( $post_type_object->name, [ 'attachment', 'revision' ], true ) ) {
593✔
141
                        $connections['preview'] = [
593✔
142
                                'toType'             => $post_type_object->graphql_single_name,
593✔
143
                                'connectionTypeName' => ucfirst( $post_type_object->graphql_single_name ) . 'ToPreviewConnection',
593✔
144
                                'oneToOne'           => true,
593✔
145
                                'deprecationReason'  => ( true === $post_type_object->publicly_queryable || true === $post_type_object->public ) ? null
593✔
146
                                        : sprintf(
593✔
147
                                                // translators: %s is the post type's GraphQL name.
148
                                                __( 'The "%s" Type is not publicly queryable and does not support previews. This field will be removed in the future.', 'wp-graphql' ),
593✔
149
                                                WPGraphQL\Utils\Utils::format_type_name( $post_type_object->graphql_single_name )
593✔
150
                                        ),
593✔
151
                                'resolve'            => static function ( Post $post, $args, AppContext $context, ResolveInfo $info ) {
593✔
152
                                        if ( $post->isRevision ) {
10✔
153
                                                return null;
×
154
                                        }
155

156
                                        if ( empty( $post->previewRevisionDatabaseId ) ) {
10✔
157
                                                return null;
1✔
158
                                        }
159

160
                                        $resolver = new PostObjectConnectionResolver( $post, $args, $context, $info, 'revision' );
9✔
161
                                        $resolver->set_query_arg( 'p', $post->previewRevisionDatabaseId );
9✔
162

163
                                        return $resolver->one_to_one()->get_connection();
9✔
164
                                },
593✔
165
                        ];
593✔
166
                }
167

168
                // Revisions.
169
                if ( true === post_type_supports( $post_type_object->name, 'revisions' ) ) {
593✔
170
                        $connections['revisions'] = [
593✔
171
                                'connectionTypeName' => ucfirst( $post_type_object->graphql_single_name ) . 'ToRevisionConnection',
593✔
172
                                'toType'             => $post_type_object->graphql_single_name,
593✔
173
                                'queryClass'         => 'WP_Query',
593✔
174
                                'connectionArgs'     => PostObjects::get_connection_args( [], $post_type_object ),
593✔
175
                                'resolve'            => static function ( Post $post, $args, $context, $info ) {
593✔
176
                                        $resolver = new PostObjectConnectionResolver( $post, $args, $context, $info, 'revision' );
3✔
177
                                        $resolver->set_query_arg( 'post_parent', $post->databaseId );
3✔
178

179
                                        return $resolver->get_connection();
3✔
180
                                },
593✔
181
                        ];
593✔
182
                }
183

184
                // Used to ensure TermNode connection doesn't get registered multiple times.
185
                $already_registered = false;
593✔
186
                $allowed_taxonomies = WPGraphQL::get_allowed_taxonomies( 'objects' );
593✔
187

188
                foreach ( $allowed_taxonomies as $tax_object ) {
593✔
189
                        if ( ! in_array( $post_type_object->name, $tax_object->object_type, true ) ) {
593✔
190
                                continue;
592✔
191
                        }
192

193
                        // TermNode.
194
                        if ( ! $already_registered ) {
593✔
195
                                $connections['terms'] = [
593✔
196
                                        'toType'         => 'TermNode',
593✔
197
                                        'queryClass'     => 'WP_Term_Query',
593✔
198
                                        'connectionArgs' => TermObjects::get_connection_args(
593✔
199
                                                [
593✔
200
                                                        'taxonomies' => [
593✔
201
                                                                'type'        => [ 'list_of' => 'TaxonomyEnum' ],
593✔
202
                                                                'description' => static function () {
593✔
203
                                                                        return __( 'The Taxonomy to filter terms by', 'wp-graphql' );
14✔
204
                                                                },
593✔
205
                                                        ],
593✔
206
                                                ]
593✔
207
                                        ),
593✔
208
                                        'resolve'        => static function ( Post $post, $args, AppContext $context, ResolveInfo $info ) {
593✔
209
                                                $taxonomies = \WPGraphQL::get_allowed_taxonomies();
×
210
                                                $object_id  = true === $post->isPreview && ! empty( $post->parentDatabaseId ) ? $post->parentDatabaseId : $post->databaseId;
×
211

212
                                                if ( empty( $object_id ) ) {
×
213
                                                        return null;
×
214
                                                }
215

216
                                                $resolver = new TermObjectConnectionResolver( $post, $args, $context, $info, $taxonomies );
×
217
                                                $resolver->set_query_arg( 'object_ids', absint( $object_id ) );
×
218
                                                return $resolver->get_connection();
×
219
                                        },
593✔
220
                                ];
593✔
221

222
                                // We won't need to register this connection again.
223
                                $already_registered = true;
593✔
224
                        }
225

226
                        // TermObjects.
227
                        $connections[ $tax_object->graphql_plural_name ] = [
593✔
228
                                'toType'         => $tax_object->graphql_single_name,
593✔
229
                                'queryClass'     => 'WP_Term_Query',
593✔
230
                                'connectionArgs' => TermObjects::get_connection_args(),
593✔
231
                                'resolve'        => static function ( Post $post, $args, AppContext $context, $info ) use ( $tax_object ) {
593✔
232
                                        $object_id = true === $post->isPreview && ! empty( $post->parentDatabaseId ) ? $post->parentDatabaseId : $post->databaseId;
15✔
233

234
                                        if ( empty( $object_id ) || ! absint( $object_id ) ) {
15✔
235
                                                return null;
×
236
                                        }
237

238
                                        $resolver = new TermObjectConnectionResolver( $post, $args, $context, $info, $tax_object->name );
15✔
239
                                        $resolver->set_query_arg( 'object_ids', absint( $object_id ) );
15✔
240

241
                                        return $resolver->get_connection();
15✔
242
                                },
593✔
243
                        ];
593✔
244
                }
245

246
                // Deprecated connections.
247
                if ( ! $post_type_object->hierarchical &&
593✔
248
                        ! in_array(
593✔
249
                                $post_type_object->name,
593✔
250
                                [
593✔
251
                                        'attachment',
593✔
252
                                        'revision',
593✔
253
                                ],
593✔
254
                                true
593✔
255
                        ) ) {
593✔
256
                        $connections['ancestors'] = [
593✔
257
                                'toType'            => $post_type_object->graphql_single_name,
593✔
258
                                'description'       => static function () {
593✔
259
                                        return __( 'The ancestors of the content node.', 'wp-graphql' );
19✔
260
                                },
593✔
261
                                'deprecationReason' => static function () {
593✔
262
                                        return __( 'This content type is not hierarchical and typically will not have ancestors', 'wp-graphql' );
19✔
263
                                },
593✔
264
                                'resolve'           => static function () {
593✔
265
                                        return null;
×
266
                                },
593✔
267
                        ];
593✔
268
                        $connections['parent']    = [
593✔
269
                                'toType'            => $post_type_object->graphql_single_name,
593✔
270
                                'oneToOne'          => true,
593✔
271
                                'description'       => static function () {
593✔
272
                                        return __( 'The parent of the content node.', 'wp-graphql' );
19✔
273
                                },
593✔
274
                                'deprecationReason' => static function () {
593✔
275
                                        return __( 'This content type is not hierarchical and typically will not have a parent', 'wp-graphql' );
19✔
276
                                },
593✔
277
                                'resolve'           => static function () {
593✔
278
                                        return null;
×
279
                                },
593✔
280
                        ];
593✔
281
                }
282

283
                // Merge with connections set in register_post_type.
284
                if ( ! empty( $post_type_object->graphql_connections ) ) {
593✔
285
                        $connections = array_merge( $connections, $post_type_object->graphql_connections );
1✔
286
                }
287

288
                // Remove excluded connections.
289
                if ( ! empty( $post_type_object->graphql_exclude_connections ) ) {
593✔
290
                        foreach ( $post_type_object->graphql_exclude_connections as $connection_name ) {
1✔
291
                                unset( $connections[ lcfirst( $connection_name ) ] );
1✔
292
                        }
293
                }
294

295
                return $connections;
593✔
296
        }
297

298
        /**
299
         * Gets all the interfaces for the given post type.
300
         *
301
         * @param \WP_Post_Type $post_type_object Post type.
302
         *
303
         * @return string[]
304
         */
305
        protected static function get_interfaces( WP_Post_Type $post_type_object ) {
593✔
306
                $interfaces = [ 'Node', 'ContentNode', 'DatabaseIdentifier', 'NodeWithTemplate' ];
593✔
307

308
                if ( true === $post_type_object->public ) {
593✔
309
                        $interfaces[] = 'UniformResourceIdentifiable';
593✔
310
                }
311

312
                // Only post types that are publicly_queryable are previewable
313
                if ( 'attachment' !== $post_type_object->name && ( true === $post_type_object->publicly_queryable || true === $post_type_object->public ) ) {
593✔
314
                        $interfaces[] = 'Previewable';
593✔
315
                }
316

317
                if ( post_type_supports( $post_type_object->name, 'title' ) ) {
593✔
318
                        $interfaces[] = 'NodeWithTitle';
593✔
319
                }
320

321
                if ( post_type_supports( $post_type_object->name, 'editor' ) ) {
593✔
322
                        $interfaces[] = 'NodeWithContentEditor';
593✔
323
                }
324

325
                if ( post_type_supports( $post_type_object->name, 'author' ) ) {
593✔
326
                        $interfaces[] = 'NodeWithAuthor';
593✔
327
                }
328

329
                if ( post_type_supports( $post_type_object->name, 'thumbnail' ) ) {
593✔
330
                        $interfaces[] = 'NodeWithFeaturedImage';
593✔
331
                }
332

333
                if ( post_type_supports( $post_type_object->name, 'excerpt' ) ) {
593✔
334
                        $interfaces[] = 'NodeWithExcerpt';
593✔
335
                }
336

337
                if ( post_type_supports( $post_type_object->name, 'comments' ) ) {
593✔
338
                        $interfaces[] = 'NodeWithComments';
593✔
339
                }
340

341
                if ( post_type_supports( $post_type_object->name, 'trackbacks' ) ) {
593✔
342
                        $interfaces[] = 'NodeWithTrackbacks';
593✔
343
                }
344

345
                if ( post_type_supports( $post_type_object->name, 'revisions' ) ) {
593✔
346
                        $interfaces[] = 'NodeWithRevisions';
593✔
347
                }
348

349
                if ( post_type_supports( $post_type_object->name, 'page-attributes' ) ) {
593✔
350
                        $interfaces[] = 'NodeWithPageAttributes';
592✔
351
                }
352

353
                if ( $post_type_object->hierarchical || in_array(
593✔
354
                        $post_type_object->name,
593✔
355
                        [
593✔
356
                                'attachment',
593✔
357
                                'revision',
593✔
358
                        ],
593✔
359
                        true
593✔
360
                ) ) {
593✔
361
                        $interfaces[] = 'HierarchicalContentNode';
592✔
362
                }
363

364
                if ( true === $post_type_object->show_in_nav_menus ) {
593✔
365
                        $interfaces[] = 'MenuItemLinkable';
593✔
366
                }
367

368
                // Merge with interfaces set in register_post_type.
369
                if ( ! empty( $post_type_object->graphql_interfaces ) ) {
593✔
370
                        $interfaces = array_merge( $interfaces, $post_type_object->graphql_interfaces );
1✔
371
                }
372

373
                // Remove excluded interfaces.
374
                if ( ! empty( $post_type_object->graphql_exclude_interfaces ) ) {
593✔
375
                        $interfaces = array_diff( $interfaces, $post_type_object->graphql_exclude_interfaces );
1✔
376
                }
377

378
                return $interfaces;
593✔
379
        }
380

381
        /**
382
         * Registers common post type fields on schema type corresponding to provided post type object.
383
         *
384
         * @param \WP_Post_Type $post_type_object Post type.
385
         *
386
         * @return array<string,array<string,mixed>>
387
         * @todo make protected after \Type\ObjectType\PostObject::get_fields() is removed.
388
         */
389
        public static function get_fields( WP_Post_Type $post_type_object ) {
593✔
390
                $single_name = $post_type_object->graphql_single_name;
593✔
391
                $fields      = [
593✔
392
                        'id'                => [
593✔
393
                                'description' => static function () use ( $post_type_object ) {
593✔
394
                                        return sprintf(
20✔
395
                                                /* translators: %s: custom post-type name */
396
                                                __( 'The globally unique identifier of the %s object.', 'wp-graphql' ),
20✔
397
                                                $post_type_object->name
20✔
398
                                        );
20✔
399
                                },
593✔
400
                        ],
593✔
401
                        $single_name . 'Id' => [
593✔
402
                                'type'              => [
593✔
403
                                        'non_null' => 'Int',
593✔
404
                                ],
593✔
405
                                'deprecationReason' => static function () {
593✔
406
                                        return __( 'Deprecated in favor of the databaseId field', 'wp-graphql' );
20✔
407
                                },
593✔
408
                                'description'       => static function () {
593✔
409
                                        return __( 'The id field matches the WP_Post->ID field.', 'wp-graphql' );
20✔
410
                                },
593✔
411
                                'resolve'           => static function ( Post $post ) {
593✔
412
                                        return absint( $post->databaseId );
50✔
413
                                },
593✔
414
                        ],
593✔
415
                        'hasPassword'       => [
593✔
416
                                'type'        => 'Boolean',
593✔
417
                                'description' => static function () use ( $post_type_object ) {
593✔
418
                                        return sprintf(
20✔
419
                                                // translators: %s: custom post-type name.
420
                                                __( 'Whether the %s object is password protected.', 'wp-graphql' ),
20✔
421
                                                $post_type_object->name
20✔
422
                                        );
20✔
423
                                },
593✔
424
                        ],
593✔
425
                        'password'          => [
593✔
426
                                'type'        => 'String',
593✔
427
                                'description' => static function () use ( $post_type_object ) {
593✔
428
                                        return sprintf(
20✔
429
                                                // translators: %s: custom post-type name.
430
                                                __( 'The password for the %s object.', 'wp-graphql' ),
20✔
431
                                                $post_type_object->name
20✔
432
                                        );
20✔
433
                                },
593✔
434
                        ],
593✔
435
                ];
593✔
436

437
                if ( 'page' === $post_type_object->name ) {
593✔
438
                        $fields['isFrontPage'] = [
592✔
439
                                'type'        => [ 'non_null' => 'Bool' ],
592✔
440
                                'description' => static function () {
592✔
441
                                        return __( 'Whether this page is set to the static front page.', 'wp-graphql' );
19✔
442
                                },
592✔
443
                        ];
592✔
444

445
                        $fields['isPostsPage'] = [
592✔
446
                                'type'        => [ 'non_null' => 'Bool' ],
592✔
447
                                'description' => static function () {
592✔
448
                                        return __( 'Whether this page is set to the blog posts page.', 'wp-graphql' );
19✔
449
                                },
592✔
450
                        ];
592✔
451

452
                        $fields['isPrivacyPage'] = [
592✔
453
                                'type'        => [ 'non_null' => 'Bool' ],
592✔
454
                                'description' => static function () {
592✔
455
                                        return __( 'Whether this page is set to the privacy page.', 'wp-graphql' );
19✔
456
                                },
592✔
457
                        ];
592✔
458
                }
459

460
                if ( 'post' === $post_type_object->name ) {
593✔
461
                        $fields['isSticky'] = [
593✔
462
                                'type'        => [ 'non_null' => 'Bool' ],
593✔
463
                                'description' => static function () {
593✔
464
                                        return __( 'Whether this page is sticky', 'wp-graphql' );
18✔
465
                                },
593✔
466
                        ];
593✔
467
                }
468

469
                // Merge with fields set in register_post_type.
470
                if ( ! empty( $post_type_object->graphql_fields ) ) {
593✔
471
                        $fields = array_merge( $fields, $post_type_object->graphql_fields );
2✔
472
                }
473

474
                // Remove excluded fields.
475
                if ( ! empty( $post_type_object->graphql_exclude_fields ) ) {
593✔
476
                        foreach ( $post_type_object->graphql_exclude_fields as $field_name ) {
1✔
477
                                unset( $fields[ $field_name ] );
1✔
478
                        }
479
                }
480

481
                return $fields;
593✔
482
        }
483

484
        /**
485
         * Register fields to the Type used for attachments (MediaItem).
486
         *
487
         * @param \WP_Post_Type $post_type_object Post type.
488
         */
489
        private static function register_attachment_fields( WP_Post_Type $post_type_object ): void {
592✔
490
                /**
491
                 * Register fields custom to the MediaItem Type
492
                 */
493
                register_graphql_fields(
592✔
494
                        $post_type_object->graphql_single_name,
592✔
495
                        [
592✔
496
                                'caption'      => [
592✔
497
                                        'type'        => 'String',
592✔
498
                                        'description' => static function () {
592✔
499
                                                return __( 'The caption for the resource', 'wp-graphql' );
18✔
500
                                        },
592✔
501
                                        'args'        => [
592✔
502
                                                'format' => [
592✔
503
                                                        'type'        => 'PostObjectFieldFormatEnum',
592✔
504
                                                        'description' => static function () {
592✔
505
                                                                return __( 'Format of the field output', 'wp-graphql' );
18✔
506
                                                        },
592✔
507
                                                ],
592✔
508
                                        ],
592✔
509
                                        'resolve'     => static function ( $source, $args ) {
592✔
510
                                                if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
7✔
511
                                                        // @codingStandardsIgnoreLine.
512
                                                        return $source->captionRaw;
×
513
                                                }
514

515
                                                // @codingStandardsIgnoreLine.
516
                                                return $source->captionRendered;
7✔
517
                                        },
592✔
518
                                ],
592✔
519
                                'altText'      => [
592✔
520
                                        'type'        => 'String',
592✔
521
                                        'description' => static function () {
592✔
522
                                                return __( 'Alternative text to display when resource is not displayed', 'wp-graphql' );
18✔
523
                                        },
592✔
524
                                ],
592✔
525
                                'srcSet'       => [
592✔
526
                                        'type'        => 'string',
592✔
527
                                        'args'        => [
592✔
528
                                                'size' => [
592✔
529
                                                        'type'        => 'MediaItemSizeEnum',
592✔
530
                                                        'description' => static function () {
592✔
531
                                                                return __( 'Size of the MediaItem to calculate srcSet with', 'wp-graphql' );
18✔
532
                                                        },
592✔
533
                                                ],
592✔
534
                                        ],
592✔
535
                                        'description' => static function () {
592✔
536
                                                return __( 'The srcset attribute specifies the URL of the image to use in different situations. It is a comma separated string of urls and their widths.', 'wp-graphql' );
18✔
537
                                        },
592✔
538
                                        'resolve'     => static function ( $source, $args ) {
592✔
539
                                                $size = 'medium';
3✔
540
                                                if ( ! empty( $args['size'] ) ) {
3✔
541
                                                        $size = $args['size'];
1✔
542
                                                }
543

544
                                                $src_set = wp_get_attachment_image_srcset( $source->ID, $size );
3✔
545

546
                                                return ! empty( $src_set ) ? $src_set : null;
3✔
547
                                        },
592✔
548
                                ],
592✔
549
                                'sizes'        => [
592✔
550
                                        'type'        => 'string',
592✔
551
                                        'args'        => [
592✔
552
                                                'size' => [
592✔
553
                                                        'type'        => 'MediaItemSizeEnum',
592✔
554
                                                        'description' => static function () {
592✔
555
                                                                return __( 'Size of the MediaItem to calculate sizes with', 'wp-graphql' );
18✔
556
                                                        },
592✔
557
                                                ],
592✔
558
                                        ],
592✔
559
                                        'description' => static function () {
592✔
560
                                                return __( 'The sizes attribute value for an image.', 'wp-graphql' );
18✔
561
                                        },
592✔
562
                                        'resolve'     => static function ( $source, $args ) {
592✔
563
                                                $size = 'medium';
1✔
564
                                                if ( ! empty( $args['size'] ) ) {
1✔
565
                                                        $size = $args['size'];
1✔
566
                                                }
567

568
                                                $image = wp_get_attachment_image_src( $source->ID, $size );
1✔
569
                                                if ( $image ) {
1✔
570
                                                        list( $src, $width, $height ) = $image;
1✔
571
                                                        $sizes                        = wp_calculate_image_sizes(
1✔
572
                                                                [
1✔
573
                                                                        absint( $width ),
1✔
574
                                                                        absint( $height ),
1✔
575
                                                                ],
1✔
576
                                                                $src,
1✔
577
                                                                null,
1✔
578
                                                                $source->ID
1✔
579
                                                        );
1✔
580

581
                                                        return ! empty( $sizes ) ? $sizes : null;
1✔
582
                                                }
583

584
                                                return null;
×
585
                                        },
592✔
586
                                ],
592✔
587
                                'description'  => [
592✔
588
                                        'type'        => 'String',
592✔
589
                                        'description' => static function () {
592✔
590
                                                return __( 'Description of the image (stored as post_content)', 'wp-graphql' );
18✔
591
                                        },
592✔
592
                                        'args'        => [
592✔
593
                                                'format' => [
592✔
594
                                                        'type'        => 'PostObjectFieldFormatEnum',
592✔
595
                                                        'description' => static function () {
592✔
596
                                                                return __( 'Format of the field output', 'wp-graphql' );
18✔
597
                                                        },
592✔
598
                                                ],
592✔
599
                                        ],
592✔
600
                                        'resolve'     => static function ( $source, $args ) {
592✔
601
                                                if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
8✔
602
                                                        // @codingStandardsIgnoreLine.
603
                                                        return $source->descriptionRaw;
×
604
                                                }
605

606
                                                // @codingStandardsIgnoreLine.
607
                                                return $source->descriptionRendered;
8✔
608
                                        },
592✔
609
                                ],
592✔
610
                                'mediaItemUrl' => [
592✔
611
                                        'type'        => 'String',
592✔
612
                                        'description' => static function () {
592✔
613
                                                return __( 'Url of the mediaItem', 'wp-graphql' );
18✔
614
                                        },
592✔
615
                                ],
592✔
616
                                'mediaType'    => [
592✔
617
                                        'type'        => 'String',
592✔
618
                                        'description' => static function () {
592✔
619
                                                return __( 'Type of resource', 'wp-graphql' );
18✔
620
                                        },
592✔
621
                                ],
592✔
622
                                'sourceUrl'    => [
592✔
623
                                        'type'        => 'String',
592✔
624
                                        'description' => static function () {
592✔
625
                                                return __( 'Url of the mediaItem', 'wp-graphql' );
18✔
626
                                        },
592✔
627
                                        'args'        => [
592✔
628
                                                'size' => [
592✔
629
                                                        'type'        => 'MediaItemSizeEnum',
592✔
630
                                                        'description' => static function () {
592✔
631
                                                                return __( 'Size of the MediaItem to return', 'wp-graphql' );
18✔
632
                                                        },
592✔
633
                                                ],
592✔
634
                                        ],
592✔
635
                                        'resolve'     => static function ( $image, $args ) {
592✔
636
                                                if ( empty( $args['size'] ) ) {
8✔
637
                                                        return $image->sourceUrl;
7✔
638
                                                }
639

640
                                                // @todo why do we coerce full to large?
641
                                                $size = 'full' === $args['size'] ? 'large' : $args['size'];
2✔
642

643
                                                /** @var \WPGraphQL\Model\Post $image */
644
                                                return $image->get_source_url_by_size( $size );
2✔
645
                                        },
592✔
646
                                ],
592✔
647
                                'file'         => [
592✔
648
                                        'type'        => 'String',
592✔
649
                                        'description' => static function () {
592✔
650
                                                return __( 'The filename of the mediaItem for the specified size (default size is full)', 'wp-graphql' );
18✔
651
                                        },
592✔
652
                                        'args'        => [
592✔
653
                                                'size' => [
592✔
654
                                                        'type'        => 'MediaItemSizeEnum',
592✔
655
                                                        'description' => static function () {
592✔
656
                                                                return __( 'Size of the MediaItem to return', 'wp-graphql' );
18✔
657
                                                        },
592✔
658
                                                ],
592✔
659
                                        ],
592✔
660
                                        'resolve'     => static function ( $source, $args ) {
592✔
661
                                                // If a size is specified, get the size-specific filename
662
                                                if ( ! empty( $args['size'] ) ) {
1✔
663
                                                        $size = 'full' === $args['size'] ? 'large' : $args['size'];
1✔
664

665
                                                        // Get the metadata which contains size information
666
                                                        $metadata = wp_get_attachment_metadata( $source->databaseId );
1✔
667

668
                                                        if ( ! empty( $metadata['sizes'][ $size ]['file'] ) ) {
1✔
669
                                                                return $metadata['sizes'][ $size ]['file'];
1✔
670
                                                        }
671
                                                }
672

673
                                                // Default to original file
674
                                                $attached_file = get_post_meta( $source->databaseId, '_wp_attached_file', true );
1✔
675
                                                return ! empty( $attached_file ) ? basename( $attached_file ) : null;
1✔
676
                                        },
592✔
677
                                ],
592✔
678
                                'filePath'     => [
592✔
679
                                        'type'        => 'String',
592✔
680
                                        'description' => static function () {
592✔
681
                                                return __( 'The path to the original file relative to the uploads directory', 'wp-graphql' );
18✔
682
                                        },
592✔
683
                                        'args'        => [
592✔
684
                                                'size' => [
592✔
685
                                                        'type'        => 'MediaItemSizeEnum',
592✔
686
                                                        'description' => static function () {
592✔
687
                                                                return __( 'Size of the MediaItem to return', 'wp-graphql' );
18✔
688
                                                        },
592✔
689
                                                ],
592✔
690
                                        ],
592✔
691
                                        'resolve'     => static function ( $source, $args ) {
592✔
692
                                                // Get the upload directory info
693
                                                $upload_dir           = wp_upload_dir();
1✔
694
                                                $relative_upload_path = wp_make_link_relative( $upload_dir['baseurl'] );
1✔
695

696
                                                // If a size is specified, get the size-specific path
697
                                                if ( ! empty( $args['size'] ) ) {
1✔
698
                                                        $size = 'full' === $args['size'] ? 'large' : $args['size'];
1✔
699

700
                                                        // Get the metadata which contains size information
701
                                                        $metadata = wp_get_attachment_metadata( $source->databaseId );
1✔
702

703
                                                        if ( ! empty( $metadata['sizes'][ $size ]['file'] ) ) {
1✔
704
                                                                $file_path = $metadata['file'];
1✔
705
                                                                return path_join( $relative_upload_path, dirname( $file_path ) . '/' . $metadata['sizes'][ $size ]['file'] );
1✔
706
                                                        }
707
                                                }
708

709
                                                // Default to original file path
710
                                                $attached_file = get_post_meta( $source->databaseId, '_wp_attached_file', true );
1✔
711

712
                                                if ( empty( $attached_file ) ) {
1✔
713
                                                        return null;
×
714
                                                }
715

716
                                                return path_join( $relative_upload_path, $attached_file );
1✔
717
                                        },
592✔
718
                                ],
592✔
719
                                'fileSize'     => [
592✔
720
                                        'type'        => 'Int',
592✔
721
                                        'description' => static function () {
592✔
722
                                                return __( 'The filesize in bytes of the resource', 'wp-graphql' );
18✔
723
                                        },
592✔
724
                                        'args'        => [
592✔
725
                                                'size' => [
592✔
726
                                                        'type'        => 'MediaItemSizeEnum',
592✔
727
                                                        'description' => static function () {
592✔
728
                                                                return __( 'Size of the MediaItem to return', 'wp-graphql' );
18✔
729
                                                        },
592✔
730
                                                ],
592✔
731
                                        ],
592✔
732
                                        'resolve'     => static function ( $image, $args ) {
592✔
733
                                                /**
734
                                                 * By default, use the mediaItemUrl.
735
                                                 *
736
                                                 * @var \WPGraphQL\Model\Post $image
737
                                                 */
738
                                                $source_url = $image->mediaItemUrl;
3✔
739

740
                                                // If there's a url for the provided size, use that instead.
741
                                                if ( ! empty( $args['size'] ) ) {
3✔
742
                                                        $size = ( 'full' === $args['size'] ) ? 'large' : $args['size'];
1✔
743

744
                                                        $source_url = $image->get_source_url_by_size( $size ) ?: $source_url;
1✔
745
                                                }
746

747
                                                // If there's no source_url, return null.
748
                                                if ( empty( $source_url ) ) {
3✔
749
                                                        return null;
×
750
                                                }
751

752
                                                $path_parts    = pathinfo( $source_url );
3✔
753
                                                $original_file = get_attached_file( absint( $image->databaseId ) );
3✔
754
                                                $filesize_path = ! empty( $original_file ) ? path_join( dirname( $original_file ), $path_parts['basename'] ) : null;
3✔
755

756
                                                return ! empty( $filesize_path ) ? filesize( $filesize_path ) : null;
3✔
757
                                        },
592✔
758
                                ],
592✔
759
                                'mimeType'     => [
592✔
760
                                        'type'        => 'String',
592✔
761
                                        'description' => static function () {
592✔
762
                                                return __( 'The mime type of the mediaItem', 'wp-graphql' );
18✔
763
                                        },
592✔
764
                                ],
592✔
765
                                'mediaDetails' => [
592✔
766
                                        'type'        => 'MediaDetails',
592✔
767
                                        'description' => static function () {
592✔
768
                                                return __( 'Details about the mediaItem', 'wp-graphql' );
18✔
769
                                        },
592✔
770
                                ],
592✔
771
                        ]
592✔
772
                );
592✔
773
        }
774
}
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