PluginProbe
WPGraphQL / trunk
WPGraphQL vtrunk
2.22.3 2.22.2 2.22.1 2.22.0 2.21.1 2.21.0 2.20.0 2.19.0 2.18.0 2.17.0 2.16.0 2.15.1 2.15.0 2.14.1 2.14.0 2.13.0 2.2.0 2.3.0 2.3.3 2.3.6 2.3.8 2.5.0 2.5.1 2.5.2 2.5.3 All 177 releases
wp-graphql / src / Mutation / CommentCreate.php

CommentCreate.php in WPGraphQL trunk, at src/Mutation/CommentCreate.php

230 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPGraphQL\Mutation;
4
5 use GraphQL\Error\UserError;
6 use GraphQL\Type\Definition\ResolveInfo;
7 use WPGraphQL\AppContext;
8 use WPGraphQL\Data\CommentMutation;
9
10 class CommentCreate {
11 /**
12 * Registers the CommentCreate mutation.
13 *
14 * @return void
15 * @throws \Exception
16 */
17 public static function register_mutation() {
18 register_graphql_mutation(
19 'createComment',
20 [
21 'inputFields' => self::get_input_fields(),
22 'outputFields' => self::get_output_fields(),
23 'mutateAndGetPayload' => self::mutate_and_get_payload(),
24 ]
25 );
26 }
27
28 /**
29 * Defines the mutation input field configuration.
30 *
31 * @return array<string,array<string,mixed>>
32 */
33 public static function get_input_fields() {
34 return [
35 'approved' => [
36 'type' => 'String',
37 'description' => static function () {
38 return __( 'The approval status of the comment.', 'wp-graphql' );
39 },
40 'deprecationReason' => static function () {
41 return __( 'Deprecated in favor of the status field', 'wp-graphql' );
42 },
43 ],
44 'author' => [
45 'type' => 'String',
46 'description' => static function () {
47 return __( 'The name of the comment\'s author.', 'wp-graphql' );
48 },
49 ],
50 'authorEmail' => [
51 'type' => 'String',
52 'description' => static function () {
53 return __( 'The email of the comment\'s author.', 'wp-graphql' );
54 },
55 ],
56 'authorUrl' => [
57 'type' => 'String',
58 'description' => static function () {
59 return __( 'The url of the comment\'s author.', 'wp-graphql' );
60 },
61 ],
62 'commentOn' => [
63 'type' => 'Int',
64 'description' => static function () {
65 return __( 'The database ID of the post object the comment belongs to.', 'wp-graphql' );
66 },
67 ],
68 'content' => [
69 'type' => 'String',
70 'description' => static function () {
71 return __( 'Content of the comment.', 'wp-graphql' );
72 },
73 ],
74 'date' => [
75 'type' => 'String',
76 'description' => static function () {
77 return __( 'The date of the object. Preferable to enter as year/month/day ( e.g. 01/31/2017 ) as it will rearrange date as fit if it is not specified. Incomplete dates may have unintended results for example, "2017" as the input will use current date with timestamp 20:17 ', 'wp-graphql' );
78 },
79 ],
80 'parent' => [
81 'type' => 'ID',
82 'description' => static function () {
83 return __( 'Parent comment ID of current comment.', 'wp-graphql' );
84 },
85 ],
86 'status' => [
87 'type' => 'CommentStatusEnum',
88 'description' => static function () {
89 return __( 'The approval status of the comment', 'wp-graphql' );
90 },
91 ],
92 'type' => [
93 'type' => 'String',
94 'description' => static function () {
95 return __( 'Type of comment.', 'wp-graphql' );
96 },
97 ],
98 ];
99 }
100
101 /**
102 * Defines the mutation output field configuration.
103 *
104 * @return array<string,array<string,mixed>>
105 */
106 public static function get_output_fields() {
107 return [
108 'comment' => [
109 'type' => 'Comment',
110 'description' => static function () {
111 return __( 'The comment that was created', 'wp-graphql' );
112 },
113 'resolve' => static function ( $payload, $args, AppContext $context ) {
114 if ( ! isset( $payload['id'] ) || ! absint( $payload['id'] ) ) {
115 return null;
116 }
117
118 return $context->get_loader( 'comment' )->load_deferred( absint( $payload['id'] ) );
119 },
120 ],
121 /**
122 * Comments can be created by non-authenticated users, but if the comment is not approved
123 * the user will not have access to the comment in response to the mutation.
124 *
125 * This field allows for the mutation to respond with a success message that the
126 * comment was indeed created, even if it cannot be returned in the response to respect
127 * server privacy.
128 *
129 * If the success comes back as true, the client can then use that response to
130 * dictate if they should use the input values as an optimistic response to the mutation
131 * and store in the cache, localStorage, cookie or whatever else so that the
132 * client can see their comment while it's still pending approval.
133 */
134 'success' => [
135 'type' => 'Boolean',
136 'description' => static function () {
137 return __( 'Whether the mutation succeeded. If the comment is not approved, the server will not return the comment to a non authenticated user, but a success message can be returned if the create succeeded, and the client can optimistically add the comment to the client cache', 'wp-graphql' );
138 },
139 ],
140 ];
141 }
142
143 /**
144 * Defines the mutation data modification closure.
145 *
146 * @return callable(array<string,mixed>$input,\WPGraphQL\AppContext $context,\GraphQL\Type\Definition\ResolveInfo $info):array<string,mixed>
147 */
148 public static function mutate_and_get_payload() {
149 return static function ( $input, AppContext $context, ResolveInfo $info ) {
150
151 /**
152 * Throw an exception if there's no input
153 */
154 if ( ( empty( $input ) || ! is_array( $input ) ) ) {
155 throw new UserError( esc_html__( 'Mutation not processed. There was no input for the mutation or the comment_object was invalid', 'wp-graphql' ) );
156 }
157
158 $commented_on = get_post( absint( $input['commentOn'] ) );
159
160 if ( empty( $commented_on ) ) {
161 throw new UserError( esc_html__( 'The ID of the node to comment on is invalid', 'wp-graphql' ) );
162 }
163
164 /**
165 * Stop if post not open to comments
166 */
167 if ( empty( $input['commentOn'] ) || 'closed' === $commented_on->comment_status ) {
168 throw new UserError( esc_html__( 'Sorry, this post is closed to comments at the moment', 'wp-graphql' ) );
169 }
170
171 if ( '1' === get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
172 throw new UserError( esc_html__( 'This site requires you to be logged in to leave a comment', 'wp-graphql' ) );
173 }
174
175 /**
176 * Map all of the args from GraphQL to WordPress friendly args array
177 */
178 $comment_args = [
179 'comment_author_url' => '',
180 'comment_type' => '',
181 'comment_parent' => 0,
182 'user_id' => 0,
183 'comment_date' => gmdate( 'Y-m-d H:i:s' ),
184 ];
185
186 CommentMutation::prepare_comment_object( $input, $comment_args, 'createComment' );
187
188 /**
189 * Insert the comment and retrieve the ID
190 */
191 $comment_id = wp_new_comment( $comment_args, true );
192
193 /**
194 * Throw an exception if the comment failed to be created
195 */
196 if ( is_wp_error( $comment_id ) ) {
197 $error_message = $comment_id->get_error_message();
198 if ( ! empty( $error_message ) ) {
199 throw new UserError( esc_html( $error_message ) );
200 } else {
201 throw new UserError( esc_html__( 'The object failed to create but no error was provided', 'wp-graphql' ) );
202 }
203 }
204
205 /**
206 * If the $comment_id is empty, we should throw an exception
207 */
208 if ( empty( $comment_id ) ) {
209 throw new UserError( esc_html__( 'The object failed to create', 'wp-graphql' ) );
210 }
211
212 /**
213 * This updates additional data not part of the comments table ( commentmeta, other relations, etc )
214 *
215 * The input for the commentMutation will be passed, along with the $new_comment_id for the
216 * comment that was created so that relations can be set, meta can be updated, etc.
217 */
218 CommentMutation::update_additional_comment_data( $comment_id, $input, 'createComment', $context, $info );
219
220 /**
221 * Return the comment object
222 */
223 return [
224 'id' => $comment_id,
225 'success' => true,
226 ];
227 };
228 }
229 }
230