@@ -255,6 +255,43 @@ public function register_routes() {
255
255
'callback ' => array ( $ this , 'get_forms_config ' ),
256
256
)
257
257
);
258
+
259
+ register_rest_route (
260
+ $ this ->namespace ,
261
+ $ this ->rest_base . '/export ' ,
262
+ array (
263
+ 'methods ' => \WP_REST_Server::CREATABLE ,
264
+ 'permission_callback ' => array ( $ this , 'export_permissions_check ' ),
265
+ 'callback ' => array ( $ this , 'export_responses ' ),
266
+ 'args ' => array (
267
+ 'selected ' => array (
268
+ 'type ' => 'array ' ,
269
+ 'items ' => array ( 'type ' => 'integer ' ),
270
+ 'default ' => array (),
271
+ ),
272
+ 'post ' => array (
273
+ 'type ' => 'string ' ,
274
+ 'default ' => 'all ' ,
275
+ ),
276
+ 'search ' => array (
277
+ 'type ' => 'string ' ,
278
+ 'default ' => '' ,
279
+ ),
280
+ 'status ' => array (
281
+ 'type ' => 'string ' ,
282
+ 'default ' => 'publish,draft ' ,
283
+ ),
284
+ 'before ' => array (
285
+ 'type ' => 'string ' ,
286
+ 'default ' => '' ,
287
+ ),
288
+ 'after ' => array (
289
+ 'type ' => 'string ' ,
290
+ 'default ' => '' ,
291
+ ),
292
+ ),
293
+ )
294
+ );
258
295
}
259
296
260
297
/**
@@ -1070,4 +1107,158 @@ public function get_forms_config( WP_REST_Request $request ) { // phpcs:ignore V
1070
1107
1071
1108
return rest_ensure_response ( $ config );
1072
1109
}
1110
+
1111
+ /**
1112
+ * Checks if a given request has permissions to export responses.
1113
+ *
1114
+ * @param WP_REST_Request $request The request object.
1115
+ * @return bool|WP_Error True if the request can export, error object otherwise.
1116
+ */
1117
+ public function export_permissions_check ( $ request ) { //phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
1118
+ if ( is_super_admin () ) {
1119
+ return true ;
1120
+ }
1121
+
1122
+ if ( ! is_user_member_of_blog ( get_current_user_id (), get_current_blog_id () ) ) {
1123
+ return new WP_Error (
1124
+ 'rest_user_not_member ' ,
1125
+ __ ( 'Sorry, you are not a member of this site. ' , 'jetpack-forms ' ),
1126
+ array ( 'status ' => rest_authorization_required_code () )
1127
+ );
1128
+ }
1129
+
1130
+ if ( ! current_user_can ( 'export ' ) ) {
1131
+ return new WP_Error (
1132
+ 'rest_user_cannot_export ' ,
1133
+ __ ( 'Sorry, you are not allowed to export form responses on this site. ' , 'jetpack-forms ' ),
1134
+ array ( 'status ' => rest_authorization_required_code () )
1135
+ );
1136
+ }
1137
+
1138
+ return true ;
1139
+ }
1140
+
1141
+ /**
1142
+ * Export form responses to CSV.
1143
+ *
1144
+ * @param WP_REST_Request $request The request object.
1145
+ * @return WP_REST_Response|WP_Error The response containing CSV data or error.
1146
+ */
1147
+ public function export_responses ( $ request ) {
1148
+ $ selected = $ request ->get_param ( 'selected ' );
1149
+ $ post_id = $ request ->get_param ( 'post ' );
1150
+ $ search = $ request ->get_param ( 'search ' );
1151
+ $ status = $ request ->get_param ( 'status ' );
1152
+ $ before = $ request ->get_param ( 'before ' );
1153
+ $ after = $ request ->get_param ( 'after ' );
1154
+
1155
+ $ query_args = array (
1156
+ 'post_type ' => 'feedback ' ,
1157
+ 'posts_per_page ' => -1 ,
1158
+ 'post_status ' => array ( 'publish ' , 'draft ' ),
1159
+ 'order ' => 'ASC ' ,
1160
+ 'suppress_filters ' => false ,
1161
+ );
1162
+
1163
+ if ( $ status && $ status !== 'publish,draft ' ) {
1164
+ $ query_args ['post_status ' ] = explode ( ', ' , $ status );
1165
+ }
1166
+
1167
+ if ( $ post_id && $ post_id !== 'all ' ) {
1168
+ $ query_args ['post_parent ' ] = intval ( $ post_id );
1169
+ }
1170
+
1171
+ if ( $ search ) {
1172
+ $ query_args ['s ' ] = $ search ;
1173
+ }
1174
+
1175
+ if ( ! empty ( $ selected ) ) {
1176
+ $ query_args ['post__in ' ] = array_map ( 'intval ' , $ selected );
1177
+ }
1178
+
1179
+ if ( $ before || $ after ) {
1180
+ $ date_query = array ();
1181
+ if ( $ before ) {
1182
+ $ date_query ['before ' ] = $ before ;
1183
+ }
1184
+ if ( $ after ) {
1185
+ $ date_query ['after ' ] = $ after ;
1186
+ }
1187
+ $ query_args ['date_query ' ] = array ( $ date_query );
1188
+ }
1189
+
1190
+ $ feedback_posts = get_posts ( $ query_args );
1191
+
1192
+ if ( empty ( $ feedback_posts ) ) {
1193
+ return new WP_Error ( 'no_responses ' , __ ( 'No responses found ' , 'jetpack-forms ' ), array ( 'status ' => 404 ) );
1194
+ }
1195
+
1196
+ $ data = array ();
1197
+ $ all_fields = array ();
1198
+
1199
+ foreach ( $ feedback_posts as $ post ) {
1200
+ $ post_data = array (
1201
+ 'ID ' => $ post ->ID ,
1202
+ 'Date ' => get_the_date ( 'Y-m-d H:i:s ' , $ post ),
1203
+ 'Author Name ' => get_post_meta ( $ post ->ID , '_feedback_author ' , true ),
1204
+ 'Author Email ' => get_post_meta ( $ post ->ID , '_feedback_author_email ' , true ),
1205
+ 'Author URL ' => get_post_meta ( $ post ->ID , '_feedback_author_url ' , true ),
1206
+ 'IP Address ' => get_post_meta ( $ post ->ID , '_feedback_ip ' , true ),
1207
+ 'Contact Form ' => get_the_title ( $ post ->post_parent ),
1208
+ );
1209
+
1210
+ $ all_meta = get_post_meta ( $ post ->ID );
1211
+ foreach ( $ all_meta as $ key => $ value ) {
1212
+ if ( strpos ( $ key , '_ ' ) === 0 ) {
1213
+ continue ;
1214
+ }
1215
+ $ post_data [ $ key ] = is_array ( $ value ) && count ( $ value ) === 1 ? $ value [0 ] : ( is_array ( $ value ) ? implode ( ', ' , $ value ) : $ value );
1216
+ }
1217
+
1218
+ $ all_fields = array_merge ( $ all_fields , array_keys ( $ post_data ) );
1219
+ $ data [] = $ post_data ;
1220
+ }
1221
+
1222
+ $ all_fields = array_unique ( $ all_fields );
1223
+ $ csv_data = array ( $ all_fields );
1224
+
1225
+ foreach ( $ data as $ post_data ) {
1226
+ $ row = array ();
1227
+ foreach ( $ all_fields as $ field ) {
1228
+ $ row [] = isset ( $ post_data [ $ field ] ) ? $ post_data [ $ field ] : '' ;
1229
+ }
1230
+ $ csv_data [] = $ row ;
1231
+ }
1232
+
1233
+ $ csv_content = '' ;
1234
+ foreach ( $ csv_data as $ row ) {
1235
+ $ csv_content .= '" ' . implode ( '"," ' , array_map ( 'esc_attr ' , $ row ) ) . '" ' . "\n" ;
1236
+ }
1237
+
1238
+ if ( ! empty ( $ post_id ) && $ post_id !== 'all ' ) {
1239
+ $ filename = sprintf (
1240
+ '%s - %s.csv ' ,
1241
+ \Automattic \Jetpack \Forms \ContactForm \Util::get_export_filename ( get_the_title ( (int ) $ post_id ) ),
1242
+ gmdate ( 'Y-m-d H:i ' )
1243
+ );
1244
+ } else {
1245
+ $ filename = sprintf (
1246
+ '%s - %s.csv ' ,
1247
+ \Automattic \Jetpack \Forms \ContactForm \Util::get_export_filename (),
1248
+ gmdate ( 'Y-m-d H:i ' )
1249
+ );
1250
+ }
1251
+
1252
+ return new WP_REST_Response (
1253
+ $ csv_content ,
1254
+ 200 ,
1255
+ array (
1256
+ 'Content-Type ' => 'text/csv; charset=utf-8 ' ,
1257
+ 'Content-Disposition ' => 'attachment; filename=" ' . $ filename . '" ' ,
1258
+ 'Cache-Control ' => 'no-cache, no-store, must-revalidate ' ,
1259
+ 'Pragma ' => 'no-cache ' ,
1260
+ 'Expires ' => '0 ' ,
1261
+ )
1262
+ );
1263
+ }
1073
1264
}
0 commit comments