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

wp-graphql / wp-graphql / #887

16 Jan 2025 10:08PM UTC coverage: 83.189% (-0.8%) from 83.968%
#887

push

php-coveralls

web-flow
Merge pull request #3272 from wp-graphql/release/v1.30.0

release: v1.30.0

473 of 718 new or added lines in 23 files covered. (65.88%)

2 existing lines in 2 files now uncovered.

12995 of 15621 relevant lines covered (83.19%)

298.21 hits per line

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

95.89
/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 ) {
34
                $single_name = $post_type_object->graphql_single_name;
586✔
35

36
                $config = [
586✔
37
                        /* translators: post object singular name w/ description */
38
                        'description' => sprintf( __( 'The %s type', 'wp-graphql' ), $single_name ),
586✔
39
                        'connections' => static::get_connections( $post_type_object ),
586✔
40
                        'interfaces'  => static::get_interfaces( $post_type_object ),
586✔
41
                        'fields'      => static::get_fields( $post_type_object ),
586✔
42
                        'model'       => Post::class,
586✔
43
                ];
586✔
44

45
                // Register as GraphQL objects.
46
                if ( 'object' === $post_type_object->graphql_kind ) {
586✔
47
                        register_graphql_object_type( $single_name, $config );
586✔
48

49
                        // Register fields to the Type used for attachments (MediaItem)
50
                        if ( 'attachment' === $post_type_object->name && true === $post_type_object->show_in_graphql && isset( $post_type_object->graphql_single_name ) ) {
586✔
51
                                self::register_attachment_fields( $post_type_object );
585✔
52
                        }
53

54
                        return;
586✔
55
                }
56

57
                /**
58
                 * Register as GraphQL interfaces or unions.
59
                 *
60
                 * It's assumed that the types used in `resolveType` have already been registered to the schema.
61
                 */
62

63
                // Bail early if graphql_resolve_type isnt a vallable callback.
64
                if ( empty( $post_type_object->graphql_resolve_type ) || ! is_callable( $post_type_object->graphql_resolve_type ) ) {
3✔
65
                        graphql_debug(
1✔
66
                                sprintf(
1✔
67
                                        // translators: %1$s is the post type name, %2$s is the graphql kind.
68
                                        __( '%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✔
69
                                        $single_name,
1✔
70
                                        $post_type_object->graphql_kind
1✔
71
                                ),
1✔
72
                                [ 'registered_post_type_object' => $post_type_object ]
1✔
73
                        );
1✔
74

75
                        return;
1✔
76
                }
77

78
                $config['resolveType'] = $post_type_object->graphql_resolve_type;
3✔
79

80
                if ( 'interface' === $post_type_object->graphql_kind ) {
3✔
81
                        register_graphql_interface_type( $single_name, $config );
1✔
82

83
                        return;
1✔
84
                } elseif ( 'union' === $post_type_object->graphql_kind ) {
2✔
85

86
                        // Bail early if graphql_union_types is not defined.
87
                        if ( empty( $post_type_object->graphql_union_types ) || ! is_array( $post_type_object->graphql_union_types ) ) {
2✔
88
                                graphql_debug(
1✔
89
                                        __( '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✔
90
                                        [ 'registered_post_type_object' => $post_type_object ]
1✔
91
                                );
1✔
92

93
                                return;
1✔
94
                        }
95

96
                        // Set the possible types for the union.
97
                        $config['typeNames'] = $post_type_object->graphql_union_types;
1✔
98

99
                        register_graphql_union_type( $single_name, $config );
1✔
100
                }
101
        }
102

103
        /**
104
         * Gets all the connections for the given post type.
105
         *
106
         * @param \WP_Post_Type $post_type_object
107
         *
108
         * @return array<string,array<string,mixed>>
109
         */
110
        protected static function get_connections( WP_Post_Type $post_type_object ) {
111
                $connections = [];
586✔
112

113
                // Comments.
114
                if ( post_type_supports( $post_type_object->name, 'comments' ) ) {
586✔
115
                        $connections['comments'] = [
586✔
116
                                'toType'         => 'Comment',
586✔
117
                                'connectionArgs' => Comments::get_connection_args(),
586✔
118
                                'resolve'        => static function ( Post $post, $args, $context, $info ) {
586✔
119
                                        if ( $post->isRevision ) {
3✔
120
                                                $id = $post->parentDatabaseId;
×
121
                                        } else {
122
                                                $id = $post->ID;
3✔
123
                                        }
124

125
                                        $resolver = new CommentConnectionResolver( $post, $args, $context, $info );
3✔
126

127
                                        return $resolver->set_query_arg( 'post_id', absint( $id ) )->get_connection();
3✔
128
                                },
586✔
129
                        ];
586✔
130
                }
131

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

149
                                        if ( empty( $post->previewRevisionDatabaseId ) ) {
10✔
150
                                                return null;
1✔
151
                                        }
152

153
                                        $resolver = new PostObjectConnectionResolver( $post, $args, $context, $info, 'revision' );
9✔
154
                                        $resolver->set_query_arg( 'p', $post->previewRevisionDatabaseId );
9✔
155

156
                                        return $resolver->one_to_one()->get_connection();
9✔
157
                                },
586✔
158
                        ];
586✔
159
                }
160

161
                // Revisions.
162
                if ( true === post_type_supports( $post_type_object->name, 'revisions' ) ) {
586✔
163
                        $connections['revisions'] = [
586✔
164
                                'connectionTypeName' => ucfirst( $post_type_object->graphql_single_name ) . 'ToRevisionConnection',
586✔
165
                                'toType'             => $post_type_object->graphql_single_name,
586✔
166
                                'queryClass'         => 'WP_Query',
586✔
167
                                'connectionArgs'     => PostObjects::get_connection_args( [], $post_type_object ),
586✔
168
                                'resolve'            => static function ( Post $post, $args, $context, $info ) {
586✔
169
                                        $resolver = new PostObjectConnectionResolver( $post, $args, $context, $info, 'revision' );
3✔
170
                                        $resolver->set_query_arg( 'post_parent', $post->ID );
3✔
171

172
                                        return $resolver->get_connection();
3✔
173
                                },
586✔
174
                        ];
586✔
175
                }
176

177
                // Used to ensure TermNode connection doesn't get registered multiple times.
178
                $already_registered = false;
586✔
179
                $allowed_taxonomies = WPGraphQL::get_allowed_taxonomies( 'objects' );
586✔
180

181
                foreach ( $allowed_taxonomies as $tax_object ) {
586✔
182
                        if ( ! in_array( $post_type_object->name, $tax_object->object_type, true ) ) {
586✔
183
                                continue;
585✔
184
                        }
185

186
                        // TermNode.
187
                        if ( ! $already_registered ) {
586✔
188
                                $connections['terms'] = [
586✔
189
                                        'toType'         => 'TermNode',
586✔
190
                                        'queryClass'     => 'WP_Term_Query',
586✔
191
                                        'connectionArgs' => TermObjects::get_connection_args(
586✔
192
                                                [
586✔
193
                                                        'taxonomies' => [
586✔
194
                                                                'type'        => [ 'list_of' => 'TaxonomyEnum' ],
586✔
195
                                                                'description' => __( 'The Taxonomy to filter terms by', 'wp-graphql' ),
586✔
196
                                                        ],
586✔
197
                                                ]
586✔
198
                                        ),
586✔
199
                                        'resolve'        => static function ( Post $post, $args, AppContext $context, ResolveInfo $info ) {
586✔
200
                                                $taxonomies = \WPGraphQL::get_allowed_taxonomies();
×
NEW
201
                                                $object_id  = true === $post->isPreview && ! empty( $post->parentDatabaseId ) ? $post->parentDatabaseId : $post->ID;
×
202

NEW
203
                                                if ( empty( $object_id ) ) {
×
204
                                                        return null;
×
205
                                                }
206

NEW
207
                                                $resolver = new TermObjectConnectionResolver( $post, $args, $context, $info, $taxonomies );
×
NEW
208
                                                $resolver->set_query_arg( 'object_ids', absint( $object_id ) );
×
UNCOV
209
                                                return $resolver->get_connection();
×
210
                                        },
586✔
211
                                ];
586✔
212

213
                                // We won't need to register this connection again.
214
                                $already_registered = true;
586✔
215
                        }
216

217
                        // TermObjects.
218
                        $connections[ $tax_object->graphql_plural_name ] = [
586✔
219
                                'toType'         => $tax_object->graphql_single_name,
586✔
220
                                'queryClass'     => 'WP_Term_Query',
586✔
221
                                'connectionArgs' => TermObjects::get_connection_args(),
586✔
222
                                'resolve'        => static function ( Post $post, $args, AppContext $context, $info ) use ( $tax_object ) {
586✔
223
                                        $object_id = true === $post->isPreview && ! empty( $post->parentDatabaseId ) ? $post->parentDatabaseId : $post->ID;
15✔
224

225
                                        if ( empty( $object_id ) || ! absint( $object_id ) ) {
15✔
226
                                                return null;
×
227
                                        }
228

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

232
                                        return $resolver->get_connection();
15✔
233
                                },
586✔
234
                        ];
586✔
235
                }
236

237
                // Deprecated connections.
238
                if ( ! $post_type_object->hierarchical &&
586✔
239
                        ! in_array(
586✔
240
                                $post_type_object->name,
586✔
241
                                [
586✔
242
                                        'attachment',
586✔
243
                                        'revision',
586✔
244
                                ],
586✔
245
                                true
586✔
246
                        ) ) {
586✔
247
                        $connections['ancestors'] = [
586✔
248
                                'toType'            => $post_type_object->graphql_single_name,
586✔
249
                                'description'       => __( 'The ancestors of the content node.', 'wp-graphql' ),
586✔
250
                                'deprecationReason' => __( 'This content type is not hierarchical and typically will not have ancestors', 'wp-graphql' ),
586✔
251
                                'resolve'           => static function () {
586✔
252
                                        return null;
×
253
                                },
586✔
254
                        ];
586✔
255
                        $connections['parent']    = [
586✔
256
                                'toType'            => $post_type_object->graphql_single_name,
586✔
257
                                'oneToOne'          => true,
586✔
258
                                'description'       => __( 'The parent of the content node.', 'wp-graphql' ),
586✔
259
                                'deprecationReason' => __( 'This content type is not hierarchical and typically will not have a parent', 'wp-graphql' ),
586✔
260
                                'resolve'           => static function () {
586✔
261
                                        return null;
×
262
                                },
586✔
263
                        ];
586✔
264
                }
265

266
                // Merge with connections set in register_post_type.
267
                if ( ! empty( $post_type_object->graphql_connections ) ) {
586✔
268
                        $connections = array_merge( $connections, $post_type_object->graphql_connections );
1✔
269
                }
270

271
                // Remove excluded connections.
272
                if ( ! empty( $post_type_object->graphql_exclude_connections ) ) {
586✔
273
                        foreach ( $post_type_object->graphql_exclude_connections as $connection_name ) {
1✔
274
                                unset( $connections[ lcfirst( $connection_name ) ] );
1✔
275
                        }
276
                }
277

278
                return $connections;
586✔
279
        }
280

281
        /**
282
         * Gets all the interfaces for the given post type.
283
         *
284
         * @param \WP_Post_Type $post_type_object Post type.
285
         *
286
         * @return string[]
287
         */
288
        protected static function get_interfaces( WP_Post_Type $post_type_object ) {
289
                $interfaces = [ 'Node', 'ContentNode', 'DatabaseIdentifier', 'NodeWithTemplate' ];
586✔
290

291
                if ( true === $post_type_object->public ) {
586✔
292
                        $interfaces[] = 'UniformResourceIdentifiable';
586✔
293
                }
294

295
                // Only post types that are publicly_queryable are previewable
296
                if ( 'attachment' !== $post_type_object->name && ( true === $post_type_object->publicly_queryable || true === $post_type_object->public ) ) {
586✔
297
                        $interfaces[] = 'Previewable';
586✔
298
                }
299

300
                if ( post_type_supports( $post_type_object->name, 'title' ) ) {
586✔
301
                        $interfaces[] = 'NodeWithTitle';
586✔
302
                }
303

304
                if ( post_type_supports( $post_type_object->name, 'editor' ) ) {
586✔
305
                        $interfaces[] = 'NodeWithContentEditor';
586✔
306
                }
307

308
                if ( post_type_supports( $post_type_object->name, 'author' ) ) {
586✔
309
                        $interfaces[] = 'NodeWithAuthor';
586✔
310
                }
311

312
                if ( post_type_supports( $post_type_object->name, 'thumbnail' ) ) {
586✔
313
                        $interfaces[] = 'NodeWithFeaturedImage';
586✔
314
                }
315

316
                if ( post_type_supports( $post_type_object->name, 'excerpt' ) ) {
586✔
317
                        $interfaces[] = 'NodeWithExcerpt';
586✔
318
                }
319

320
                if ( post_type_supports( $post_type_object->name, 'comments' ) ) {
586✔
321
                        $interfaces[] = 'NodeWithComments';
586✔
322
                }
323

324
                if ( post_type_supports( $post_type_object->name, 'trackbacks' ) ) {
586✔
325
                        $interfaces[] = 'NodeWithTrackbacks';
586✔
326
                }
327

328
                if ( post_type_supports( $post_type_object->name, 'revisions' ) ) {
586✔
329
                        $interfaces[] = 'NodeWithRevisions';
586✔
330
                }
331

332
                if ( post_type_supports( $post_type_object->name, 'page-attributes' ) ) {
586✔
333
                        $interfaces[] = 'NodeWithPageAttributes';
585✔
334
                }
335

336
                if ( $post_type_object->hierarchical || in_array(
586✔
337
                        $post_type_object->name,
586✔
338
                        [
586✔
339
                                'attachment',
586✔
340
                                'revision',
586✔
341
                        ],
586✔
342
                        true
586✔
343
                ) ) {
586✔
344
                        $interfaces[] = 'HierarchicalContentNode';
585✔
345
                }
346

347
                if ( true === $post_type_object->show_in_nav_menus ) {
586✔
348
                        $interfaces[] = 'MenuItemLinkable';
586✔
349
                }
350

351
                // Merge with interfaces set in register_post_type.
352
                if ( ! empty( $post_type_object->graphql_interfaces ) ) {
586✔
353
                        $interfaces = array_merge( $interfaces, $post_type_object->graphql_interfaces );
1✔
354
                }
355

356
                // Remove excluded interfaces.
357
                if ( ! empty( $post_type_object->graphql_exclude_interfaces ) ) {
586✔
358
                        $interfaces = array_diff( $interfaces, $post_type_object->graphql_exclude_interfaces );
1✔
359
                }
360

361
                return $interfaces;
586✔
362
        }
363

364
        /**
365
         * Registers common post type fields on schema type corresponding to provided post type object.
366
         *
367
         * @param \WP_Post_Type $post_type_object Post type.
368
         *
369
         * @return array<string,array<string,mixed>>
370
         * @todo make protected after \Type\ObjectType\PostObject::get_fields() is removed.
371
         */
372
        public static function get_fields( WP_Post_Type $post_type_object ) {
373
                $single_name = $post_type_object->graphql_single_name;
586✔
374
                $fields      = [
586✔
375
                        'id'                => [
586✔
376
                                'description' => sprintf(
586✔
377
                                /* translators: %s: custom post-type name */
378
                                        __( 'The globally unique identifier of the %s object.', 'wp-graphql' ),
586✔
379
                                        $post_type_object->name
586✔
380
                                ),
586✔
381
                        ],
586✔
382
                        $single_name . 'Id' => [
586✔
383
                                'type'              => [
586✔
384
                                        'non_null' => 'Int',
586✔
385
                                ],
586✔
386
                                'deprecationReason' => __( 'Deprecated in favor of the databaseId field', 'wp-graphql' ),
586✔
387
                                'description'       => __( 'The id field matches the WP_Post->ID field.', 'wp-graphql' ),
586✔
388
                                'resolve'           => static function ( Post $post ) {
586✔
389
                                        return absint( $post->ID );
50✔
390
                                },
586✔
391
                        ],
586✔
392
                        'hasPassword'       => [
586✔
393
                                'type'        => 'Boolean',
586✔
394
                                'description' => sprintf(
586✔
395
                                        // translators: %s: custom post-type name.
396
                                        __( 'Whether the %s object is password protected.', 'wp-graphql' ),
586✔
397
                                        $post_type_object->name
586✔
398
                                ),
586✔
399
                        ],
586✔
400
                        'password'          => [
586✔
401
                                'type'        => 'String',
586✔
402
                                'description' => sprintf(
586✔
403
                                        // translators: %s: custom post-type name.
404
                                        __( 'The password for the %s object.', 'wp-graphql' ),
586✔
405
                                        $post_type_object->name
586✔
406
                                ),
586✔
407
                        ],
586✔
408
                ];
586✔
409

410
                if ( 'page' === $post_type_object->name ) {
586✔
411
                        $fields['isFrontPage'] = [
585✔
412
                                'type'        => [ 'non_null' => 'Bool' ],
585✔
413
                                'description' => __( 'Whether this page is set to the static front page.', 'wp-graphql' ),
585✔
414
                        ];
585✔
415

416
                        $fields['isPostsPage'] = [
585✔
417
                                'type'        => [ 'non_null' => 'Bool' ],
585✔
418
                                'description' => __( 'Whether this page is set to the blog posts page.', 'wp-graphql' ),
585✔
419
                        ];
585✔
420

421
                        $fields['isPrivacyPage'] = [
585✔
422
                                'type'        => [ 'non_null' => 'Bool' ],
585✔
423
                                'description' => __( 'Whether this page is set to the privacy page.', 'wp-graphql' ),
585✔
424
                        ];
585✔
425
                }
426

427
                if ( 'post' === $post_type_object->name ) {
586✔
428
                        $fields['isSticky'] = [
586✔
429
                                'type'        => [ 'non_null' => 'Bool' ],
586✔
430
                                'description' => __( 'Whether this page is sticky', 'wp-graphql' ),
586✔
431
                        ];
586✔
432
                }
433

434
                // Merge with fields set in register_post_type.
435
                if ( ! empty( $post_type_object->graphql_fields ) ) {
586✔
436
                        $fields = array_merge( $fields, $post_type_object->graphql_fields );
448✔
437
                }
438

439
                // Remove excluded fields.
440
                if ( ! empty( $post_type_object->graphql_exclude_fields ) ) {
586✔
441
                        foreach ( $post_type_object->graphql_exclude_fields as $field_name ) {
447✔
442
                                unset( $fields[ $field_name ] );
447✔
443
                        }
444
                }
445

446
                return $fields;
586✔
447
        }
448

449
        /**
450
         * Register fields to the Type used for attachments (MediaItem).
451
         *
452
         * @param \WP_Post_Type $post_type_object Post type.
453
         *
454
         * @return void
455
         */
456
        private static function register_attachment_fields( WP_Post_Type $post_type_object ) {
457
                /**
458
                 * Register fields custom to the MediaItem Type
459
                 */
460
                register_graphql_fields(
585✔
461
                        $post_type_object->graphql_single_name,
585✔
462
                        [
585✔
463
                                'caption'      => [
585✔
464
                                        'type'        => 'String',
585✔
465
                                        'description' => __( 'The caption for the resource', 'wp-graphql' ),
585✔
466
                                        'args'        => [
585✔
467
                                                'format' => [
585✔
468
                                                        'type'        => 'PostObjectFieldFormatEnum',
585✔
469
                                                        'description' => __( 'Format of the field output', 'wp-graphql' ),
585✔
470
                                                ],
585✔
471
                                        ],
585✔
472
                                        'resolve'     => static function ( $source, $args ) {
585✔
473
                                                if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
7✔
474
                                                        // @codingStandardsIgnoreLine.
475
                                                        return $source->captionRaw;
×
476
                                                }
477

478
                                                // @codingStandardsIgnoreLine.
479
                                                return $source->captionRendered;
7✔
480
                                        },
585✔
481
                                ],
585✔
482
                                'altText'      => [
585✔
483
                                        'type'        => 'String',
585✔
484
                                        'description' => __( 'Alternative text to display when resource is not displayed', 'wp-graphql' ),
585✔
485
                                ],
585✔
486
                                'srcSet'       => [
585✔
487
                                        'type'        => 'string',
585✔
488
                                        'args'        => [
585✔
489
                                                'size' => [
585✔
490
                                                        'type'        => 'MediaItemSizeEnum',
585✔
491
                                                        'description' => __( 'Size of the MediaItem to calculate srcSet with', 'wp-graphql' ),
585✔
492
                                                ],
585✔
493
                                        ],
585✔
494
                                        'description' => __( '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' ),
585✔
495
                                        'resolve'     => static function ( $source, $args ) {
585✔
496
                                                $size = 'medium';
3✔
497
                                                if ( ! empty( $args['size'] ) ) {
3✔
498
                                                        $size = $args['size'];
1✔
499
                                                }
500

501
                                                $src_set = wp_get_attachment_image_srcset( $source->ID, $size );
3✔
502

503
                                                return ! empty( $src_set ) ? $src_set : null;
3✔
504
                                        },
585✔
505
                                ],
585✔
506
                                'sizes'        => [
585✔
507
                                        'type'        => 'string',
585✔
508
                                        'args'        => [
585✔
509
                                                'size' => [
585✔
510
                                                        'type'        => 'MediaItemSizeEnum',
585✔
511
                                                        'description' => __( 'Size of the MediaItem to calculate sizes with', 'wp-graphql' ),
585✔
512
                                                ],
585✔
513
                                        ],
585✔
514
                                        'description' => __( 'The sizes attribute value for an image.', 'wp-graphql' ),
585✔
515
                                        'resolve'     => static function ( $source, $args ) {
585✔
516
                                                $size = 'medium';
1✔
517
                                                if ( ! empty( $args['size'] ) ) {
1✔
518
                                                        $size = $args['size'];
1✔
519
                                                }
520

521
                                                $image = wp_get_attachment_image_src( $source->ID, $size );
1✔
522
                                                if ( $image ) {
1✔
523
                                                        list( $src, $width, $height ) = $image;
1✔
524
                                                        $sizes                        = wp_calculate_image_sizes(
1✔
525
                                                                [
1✔
526
                                                                        absint( $width ),
1✔
527
                                                                        absint( $height ),
1✔
528
                                                                ],
1✔
529
                                                                $src,
1✔
530
                                                                null,
1✔
531
                                                                $source->ID
1✔
532
                                                        );
1✔
533

534
                                                        return ! empty( $sizes ) ? $sizes : null;
1✔
535
                                                }
536

537
                                                return null;
×
538
                                        },
585✔
539
                                ],
585✔
540
                                'description'  => [
585✔
541
                                        'type'        => 'String',
585✔
542
                                        'description' => __( 'Description of the image (stored as post_content)', 'wp-graphql' ),
585✔
543
                                        'args'        => [
585✔
544
                                                'format' => [
585✔
545
                                                        'type'        => 'PostObjectFieldFormatEnum',
585✔
546
                                                        'description' => __( 'Format of the field output', 'wp-graphql' ),
585✔
547
                                                ],
585✔
548
                                        ],
585✔
549
                                        'resolve'     => static function ( $source, $args ) {
585✔
550
                                                if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
8✔
551
                                                        // @codingStandardsIgnoreLine.
552
                                                        return $source->descriptionRaw;
×
553
                                                }
554

555
                                                // @codingStandardsIgnoreLine.
556
                                                return $source->descriptionRendered;
8✔
557
                                        },
585✔
558
                                ],
585✔
559
                                'mediaItemUrl' => [
585✔
560
                                        'type'        => 'String',
585✔
561
                                        'description' => __( 'Url of the mediaItem', 'wp-graphql' ),
585✔
562
                                ],
585✔
563
                                'mediaType'    => [
585✔
564
                                        'type'        => 'String',
585✔
565
                                        'description' => __( 'Type of resource', 'wp-graphql' ),
585✔
566
                                ],
585✔
567
                                'sourceUrl'    => [
585✔
568
                                        'type'        => 'String',
585✔
569
                                        'description' => __( 'Url of the mediaItem', 'wp-graphql' ),
585✔
570
                                        'args'        => [
585✔
571
                                                'size' => [
585✔
572
                                                        'type'        => 'MediaItemSizeEnum',
585✔
573
                                                        'description' => __( 'Size of the MediaItem to return', 'wp-graphql' ),
585✔
574
                                                ],
585✔
575
                                        ],
585✔
576
                                        'resolve'     => static function ( $image, $args ) {
585✔
577
                                                if ( empty( $args['size'] ) ) {
8✔
578
                                                        return $image->sourceUrl;
7✔
579
                                                }
580

581
                                                // @todo why do we coerce full to large?
582
                                                $size = 'full' === $args['size'] ? 'large' : $args['size'];
2✔
583

584
                                                /** @var \WPGraphQL\Model\Post $image */
585
                                                return $image->get_source_url_by_size( $size );
2✔
586
                                        },
585✔
587
                                ],
585✔
588
                                'fileSize'     => [
585✔
589
                                        'type'        => 'Int',
585✔
590
                                        'description' => __( 'The filesize in bytes of the resource', 'wp-graphql' ),
585✔
591
                                        'args'        => [
585✔
592
                                                'size' => [
585✔
593
                                                        'type'        => 'MediaItemSizeEnum',
585✔
594
                                                        'description' => __( 'Size of the MediaItem to return', 'wp-graphql' ),
585✔
595
                                                ],
585✔
596
                                        ],
585✔
597
                                        'resolve'     => static function ( $image, $args ) {
585✔
598
                                                /**
599
                                                 * By default, use the mediaItemUrl.
600
                                                 *
601
                                                 * @var \WPGraphQL\Model\Post $image
602
                                                 */
603
                                                $source_url = $image->mediaItemUrl;
3✔
604

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

609
                                                        $source_url = $image->get_source_url_by_size( $size ) ?: $source_url;
1✔
610
                                                }
611

612
                                                // If there's no source_url, return null.
613
                                                if ( empty( $source_url ) ) {
3✔
614
                                                        return null;
×
615
                                                }
616

617
                                                $path_parts    = pathinfo( $source_url );
3✔
618
                                                $original_file = get_attached_file( absint( $image->databaseId ) );
3✔
619
                                                $filesize_path = ! empty( $original_file ) ? path_join( dirname( $original_file ), $path_parts['basename'] ) : null;
3✔
620

621
                                                return ! empty( $filesize_path ) ? filesize( $filesize_path ) : null;
3✔
622
                                        },
585✔
623
                                ],
585✔
624
                                'mimeType'     => [
585✔
625
                                        'type'        => 'String',
585✔
626
                                        'description' => __( 'The mime type of the mediaItem', 'wp-graphql' ),
585✔
627
                                ],
585✔
628
                                'mediaDetails' => [
585✔
629
                                        'type'        => 'MediaDetails',
585✔
630
                                        'description' => __( 'Details about the mediaItem', 'wp-graphql' ),
585✔
631
                                ],
585✔
632
                        ]
585✔
633
                );
585✔
634
        }
635
}
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