• 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

98.73
/src/Mutation/PostObjectDelete.php
1
<?php
2

3
namespace WPGraphQL\Mutation;
4

5
use GraphQL\Error\UserError;
6
use GraphQLRelay\Relay;
7
use WPGraphQL\Data\PostObjectMutation;
8
use WPGraphQL\Model\Post;
9
use WPGraphQL\Utils\Utils;
10
use WP_Post_Type;
11

12
class PostObjectDelete {
13
        /**
14
         * Registers the PostObjectDelete mutation.
15
         *
16
         * @param \WP_Post_Type $post_type_object The post type of the mutation.
17
         *
18
         * @return void
19
         * @throws \Exception
20
         */
21
        public static function register_mutation( WP_Post_Type $post_type_object ) {
593✔
22
                $mutation_name = 'delete' . ucwords( $post_type_object->graphql_single_name );
593✔
23

24
                register_graphql_mutation(
593✔
25
                        $mutation_name,
593✔
26
                        [
593✔
27
                                'inputFields'         => self::get_input_fields( $post_type_object ),
593✔
28
                                'outputFields'        => self::get_output_fields( $post_type_object ),
593✔
29
                                'mutateAndGetPayload' => self::mutate_and_get_payload( $post_type_object, $mutation_name ),
593✔
30
                        ]
593✔
31
                );
593✔
32
        }
33

34
        /**
35
         * Defines the mutation input field configuration.
36
         *
37
         * @param \WP_Post_Type $post_type_object The post type of the mutation.
38
         *
39
         * @return array<string,array<string,mixed>>
40
         */
41
        public static function get_input_fields( $post_type_object ) {
593✔
42
                return [
593✔
43
                        'id'             => [
593✔
44
                                'type'        => [
593✔
45
                                        'non_null' => 'ID',
593✔
46
                                ],
593✔
47
                                'description' => static function () use ( $post_type_object ) {
593✔
48
                                        // translators: The placeholder is the name of the post's post_type being deleted
49
                                        return sprintf( __( 'The ID of the %1$s to delete', 'wp-graphql' ), $post_type_object->graphql_single_name );
15✔
50
                                },
593✔
51
                        ],
593✔
52
                        'forceDelete'    => [
593✔
53
                                'type'        => 'Boolean',
593✔
54
                                'description' => static function () {
593✔
55
                                        return __( 'Whether the object should be force deleted instead of being moved to the trash', 'wp-graphql' );
15✔
56
                                },
593✔
57
                        ],
593✔
58
                        'ignoreEditLock' => [
593✔
59
                                'type'        => 'Boolean',
593✔
60
                                'description' => static function () {
593✔
61
                                        return __( 'Override the edit lock when another user is editing the post', 'wp-graphql' );
15✔
62
                                },
593✔
63
                        ],
593✔
64
                ];
593✔
65
        }
66

67
        /**
68
         * Defines the mutation output field configuration.
69
         *
70
         * @param \WP_Post_Type $post_type_object The post type of the mutation.
71
         *
72
         * @return array<string,array<string,mixed>>
73
         */
74
        public static function get_output_fields( WP_Post_Type $post_type_object ) {
593✔
75
                return [
593✔
76
                        'deletedId'                            => [
593✔
77
                                'type'        => 'ID',
593✔
78
                                'description' => static function () {
593✔
79
                                        return __( 'The ID of the deleted object', 'wp-graphql' );
15✔
80
                                },
593✔
81
                                'resolve'     => static function ( $payload ) {
593✔
82
                                        /** @var \WPGraphQL\Model\Post $deleted */
83
                                        $deleted = $payload['postObject'];
1✔
84

85
                                        return ! empty( $deleted->ID ) ? Relay::toGlobalId( 'post', (string) $deleted->ID ) : null;
1✔
86
                                },
593✔
87
                        ],
593✔
88
                        $post_type_object->graphql_single_name => [
593✔
89
                                'type'        => $post_type_object->graphql_single_name,
593✔
90
                                'description' => static function () {
593✔
91
                                        return __( 'The object before it was deleted', 'wp-graphql' );
15✔
92
                                },
593✔
93
                                'resolve'     => static function ( $payload ) {
593✔
94
                                        /** @var \WPGraphQL\Model\Post $deleted */
95
                                        $deleted = $payload['postObject'];
2✔
96

97
                                        return ! empty( $deleted->ID ) ? $deleted : null;
2✔
98
                                },
593✔
99
                        ],
593✔
100
                ];
593✔
101
        }
102

103
        /**
104
         * Defines the mutation data modification closure.
105
         *
106
         * @param \WP_Post_Type $post_type_object The post type of the mutation.
107
         * @param string        $mutation_name    The mutation name.
108
         *
109
         * @return callable(array<string,mixed>$input,\WPGraphQL\AppContext $context,\GraphQL\Type\Definition\ResolveInfo $info):array<string,mixed>
110
         */
111
        public static function mutate_and_get_payload( WP_Post_Type $post_type_object, string $mutation_name ) {
593✔
112
                return static function ( $input ) use ( $post_type_object ) {
593✔
113
                        // Get the database ID for the post.
114
                        $post_id = Utils::get_database_id_from_id( $input['id'] );
3✔
115

116
                        /**
117
                         * Stop now if a user isn't allowed to delete a post
118
                         */
119
                        if ( ! isset( $post_type_object->cap->delete_post ) || ! current_user_can( $post_type_object->cap->delete_post, $post_id ) ) {
3✔
120
                                // translators: the $post_type_object->graphql_plural_name placeholder is the name of the object being mutated
121
                                throw new UserError( esc_html( sprintf( __( 'Sorry, you are not allowed to delete %1$s', 'wp-graphql' ), $post_type_object->graphql_plural_name ) ) );
2✔
122
                        }
123

124
                        /**
125
                         * Check if we should force delete or not
126
                         */
127
                        $force_delete = ! empty( $input['forceDelete'] ) && true === $input['forceDelete'];
2✔
128

129
                        /**
130
                         * Get the post object before deleting it
131
                         */
132
                        $post_before_delete = ! empty( $post_id ) ? get_post( $post_id ) : null;
2✔
133

134
                        if ( empty( $post_before_delete ) ) {
2✔
135
                                throw new UserError( esc_html__( 'The post could not be deleted', 'wp-graphql' ) );
×
136
                        }
137

138
                        $post_before_delete = new Post( $post_before_delete );
2✔
139

140
                        /**
141
                         * If the post is already in the trash, and the forceDelete input was not passed,
142
                         * don't remove from the trash
143
                         */
144
                        if ( 'trash' === $post_before_delete->status && true !== $force_delete ) {
2✔
145
                                // Translators: the first placeholder is the post_type of the object being deleted and the second placeholder is the unique ID of that object
146
                                throw new UserError( esc_html( sprintf( __( 'The %1$s with id %2$s is already in the trash. To remove from the trash, use the forceDelete input', 'wp-graphql' ), $post_type_object->graphql_single_name, $post_id ) ) );
1✔
147
                        }
148

149
                        // If post is locked and the override is not specified, do not allow the edit
150
                        $locked_user_id = PostObjectMutation::check_edit_lock( $post_id, $input );
2✔
151
                        if ( false !== $locked_user_id ) {
2✔
152
                                $user         = get_userdata( (int) $locked_user_id );
1✔
153
                                $display_name = isset( $user->display_name ) ? $user->display_name : 'unknown';
1✔
154
                                /* translators: %s: User's display name. */
155
                                throw new UserError( esc_html( sprintf( __( 'You cannot delete this item. %s is currently editing.', 'wp-graphql' ), $display_name ) ) );
1✔
156
                        }
157

158
                        /**
159
                         * Delete the post
160
                         */
161
                        $deleted = wp_delete_post( (int) $post_id, $force_delete );
2✔
162

163
                        /**
164
                         * If the post was moved to the trash, spoof the object's status before returning it
165
                         */
166
                        $post_before_delete->status = ( false !== $deleted && true !== $force_delete ) ? 'trash' : $post_before_delete->status;
2✔
167

168
                        /**
169
                         * Return the deletedId and the object before it was deleted
170
                         */
171
                        return [
2✔
172
                                'postObject' => $post_before_delete,
2✔
173
                        ];
2✔
174
                };
593✔
175
        }
176
}
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