PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.0
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
← All changes | libraries/nps-survey/classes/nps-survey-script.php +209 -74 3.1.3 → 3.3.0 View file →
@@ -5,8 +5,12 @@
5 5 *
6 6 * @package {{package}}
7 7 */
8 8
9 +if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 +}
12 +
9 13 // Prevent multiple inclusions of this file.
10 14 if ( defined( 'NPS_SURVEY_SCRIPT_LOADED' ) ) {
11 15 return;
12 16 }
@@ -63,9 +67,22 @@
63 67
64 68 $plugin_slug = $vars['plugin_slug'];
65 69 $display_after = is_int( $vars['display_after'] ) ? $vars['display_after'] : 0;
66 70
67 - if ( ! self::is_show_nps_survey_form( $plugin_slug, $display_after ) ) {
71 + /**
72 + * Filter to check if the NPS survey should be shown.
73 + *
74 + * @param bool $status Whether to show the notice.
75 + * @param string $plugin_slug Plugin slug.
76 + * @since 1.0.13
77 + */
78 + $show_notice = apply_filters(
79 + 'nps_survey_show_notice',
80 + self::is_show_nps_survey_form( $plugin_slug, $display_after ),
81 + $plugin_slug
82 + );
83 +
84 + if ( ! $show_notice ) {
68 85 return;
69 86 }
70 87
71 88 $show_on_screen = ! empty( $vars['show_on_screens'] ) && is_array( $vars['show_on_screens'] ) ? $vars['show_on_screens'] : [ 'dashboard' ];
@@ -70,13 +87,14 @@
70 87
71 88 $show_on_screen = ! empty( $vars['show_on_screens'] ) && is_array( $vars['show_on_screens'] ) ? $vars['show_on_screens'] : [ 'dashboard' ];
72 89
73 90 if ( ! function_exists( 'get_current_screen' ) ) {
74 - require_once ABSPATH . '/wp-admin/includes/screen.php';
91 + return;
75 92 }
76 93 $current_screen = get_current_screen();
77 94
78 - if ( $current_screen instanceof WP_Screen && ! in_array( $current_screen->id, $show_on_screen, true ) ) {
95 + $admin_only = self::is_nps_survey_enabled_for_admin_only();
96 + if ( $admin_only && $current_screen instanceof WP_Screen && ! in_array( $current_screen->id, $show_on_screen, true ) ) {
79 97 return;
80 98 }
81 99 // Loading script here to confirm if the screen is allowed or not.
82 100 self::editor_load_scripts( $show_on_screen );
@@ -85,28 +103,8 @@
85 103 <?php
86 104 }
87 105
88 106 /**
89 - * Generate and return the Google fonts url.
90 - *
91 - * @since 1.0.2
92 - * @return string
93 - */
94 - public static function google_fonts_url() {
95 -
96 - $font_families = array(
97 - 'Figtree:400,500,600,700',
98 - );
99 -
100 - $query_args = array(
101 - 'family' => rawurlencode( implode( '|', $font_families ) ),
102 - 'subset' => rawurlencode( 'latin,latin-ext' ),
103 - );
104 -
105 - return add_query_arg( $query_args, '//fonts.googleapis.com/css' );
106 - }
107 -
108 - /**
109 107 * Load script.
110 108 *
111 109 * @param array<string> $show_on_screens An array of screen IDs where the scripts should be loaded.
112 110 * @since 1.0.0
@@ -113,9 +111,10 @@
113 111 * @return void
114 112 */
115 113 public static function editor_load_scripts( $show_on_screens ): void {
116 114
117 - if ( ! is_admin() ) {
115 + $admin_only = self::is_nps_survey_enabled_for_admin_only();
116 + if ( $admin_only && ! is_admin() ) {
118 117 return;
119 118 }
120 119
121 120 $screen = get_current_screen();
@@ -120,9 +119,9 @@
120 119
121 120 $screen = get_current_screen();
122 121 $screen_id = $screen ? $screen->id : '';
123 122
124 - if ( ! in_array( $screen_id, $show_on_screens, true ) ) {
123 + if ( $admin_only && ! in_array( $screen_id, $show_on_screens, true ) ) {
125 124 return;
126 125 }
127 126
128 127 $handle = 'nps-survey-script';
@@ -161,15 +160,15 @@
161 160
162 161 // Add localize JS.
163 162 wp_localize_script(
164 163 'nps-survey-script',
165 - 'npsSurvey',
164 + 'nps_survey_data',
166 165 $data
167 166 );
168 167
169 168 wp_enqueue_style( 'nps-survey-style', $build_url . '/style-main.css', array(), NPS_SURVEY_VER );
170 169 wp_style_add_data( 'nps-survey-style', 'rtl', 'replace' );
171 - wp_enqueue_style( 'nps-survey-google-fonts', self::google_fonts_url(), array(), 'all' );
170 + wp_enqueue_style( 'nps-survey-fonts', NPS_SURVEY_URL . 'assets/fonts/figtree.css', array(), NPS_SURVEY_VER );
172 171 }
173 172
174 173 /**
175 174 * Load all the required files in the importer.
@@ -186,9 +185,34 @@
186 185 array(
187 186 'methods' => \WP_REST_Server::CREATABLE,
188 187 'callback' => array( self::class, 'submit_rating' ),
189 188 'permission_callback' => array( self::class, 'get_item_permissions_check' ),
190 - 'args' => array(),
189 + 'args' => array(
190 + 'nps_id' => array(
191 + 'type' => 'string',
192 + 'required' => true,
193 + 'sanitize_callback' => 'sanitize_key',
194 + ),
195 + 'rating' => array(
196 + 'type' => 'integer',
197 + 'required' => true,
198 + 'validate_callback' => static function ( $value ) {
199 + return is_numeric( $value ) && (int) $value >= 0 && (int) $value <= 10;
200 + },
201 + 'sanitize_callback' => 'absint',
202 + ),
203 + 'comment' => array(
204 + 'type' => 'string',
205 + 'required' => false,
206 + 'default' => '',
207 + 'sanitize_callback' => 'sanitize_text_field',
208 + ),
209 + 'plugin_slug' => array(
210 + 'type' => 'string',
211 + 'required' => true,
212 + 'sanitize_callback' => 'sanitize_key',
213 + ),
214 + ),
191 215 ),
192 216 )
193 217 );
194 218
@@ -199,9 +223,30 @@
199 223 array(
200 224 'methods' => \WP_REST_Server::CREATABLE,
201 225 'callback' => array( self::class, 'dismiss_nps_survey_panel' ),
202 226 'permission_callback' => array( self::class, 'get_item_permissions_check' ),
203 - 'args' => array(),
227 + 'args' => array(
228 + 'nps_id' => array(
229 + 'type' => 'string',
230 + 'required' => true,
231 + 'sanitize_callback' => 'sanitize_key',
232 + ),
233 + 'plugin_slug' => array(
234 + 'type' => 'string',
235 + 'required' => true,
236 + 'sanitize_callback' => 'sanitize_key',
237 + ),
238 + 'dismiss_timespan' => array(
239 + 'type' => 'integer',
240 + 'required' => true,
241 + 'sanitize_callback' => 'absint',
242 + ),
243 + 'current_step' => array(
244 + 'type' => 'string',
245 + 'required' => true,
246 + 'sanitize_callback' => 'sanitize_text_field',
247 + ),
248 + ),
204 249 ),
205 250 )
206 251 );
207 252 }
@@ -246,12 +291,26 @@
246 291 * @param object $request WP_REST_Request Full details about the request.
247 292 * @return object|bool
248 293 */
249 294 public static function get_item_permissions_check( $request ) {
295 + /**
296 + * Filter to disable the REST API permission check for NPS Survey endpoints.
297 + *
298 + * @security WARNING: Setting this filter to `true` removes all authentication
299 + * and capability checks from the NPS Survey REST API endpoints, making them
300 + * publicly accessible to any unauthenticated request. Only use this in
301 + * controlled environments where you explicitly intend to open these endpoints.
302 + *
303 + * @param bool $disable Whether to bypass the permission check. Default false.
304 + * @since 1.0.13
305 + */
306 + if ( apply_filters( 'nps_survey_api_disable_permission_check', false ) ) {
307 + return true;
308 + }
250 309
251 310 if ( ! current_user_can( 'manage_options' ) ) {
252 311 return new \WP_Error(
253 - 'gt_rest_cannot_access',
312 + 'nps_survey_rest_cannot_access',
254 313 __( 'Sorry, you are not allowed to do that.', 'nps-survey' ),
255 314 array( 'status' => rest_authorization_required_code() )
256 315 );
257 316 }
@@ -258,13 +317,44 @@
258 317 return true;
259 318 }
260 319
261 320 /**
321 + * Method to determine if the NPS survey status update should be skipped for database option.
322 + *
323 + * @param string $nps_id NPS ID.
324 + * @param string $type Type of action (e.g., 'submit', 'dismiss').
325 + * @param array $data Additional data related to the NPS survey.
326 + *
327 + * @since 1.0.13
328 + * @return bool
329 + * @phpstan-ignore-next-line
330 + */
331 + public static function should_skip_status_update( $nps_id, $type, $data = array() ): bool {
332 + /**
333 + * Filter to determine if the NPS survey status should be updated.
334 + *
335 + * @param bool $update Default is true, can be modified by the filter.
336 + * @param array $post_data Post data being sent.
337 + * @since 1.0.13
338 + */
339 + return apply_filters(
340 + 'nps_survey_should_skip_status_update',
341 + false, // Default to false, can be modified by the filter.
342 + array_merge(
343 + $data,
344 + array(
345 + 'nps_id' => $nps_id,
346 + 'action_type' => $type,
347 + )
348 + )
349 + );
350 + }
351 +
352 + /**
262 353 * Submit Ratings.
263 354 *
264 - * @param \WP_REST_Request $request Request object.
265 - * @return void
266 - * @phpstan-ignore-next-line
355 + * @param \WP_REST_Request<array<string,mixed>> $request Request object.
356 + * @return \WP_REST_Response|\WP_Error
267 357 */
268 358 public static function submit_rating( $request ) {
269 359
270 360 $nonce = $request->get_header( 'X-WP-Nonce' );
@@ -270,18 +360,24 @@
270 360 $nonce = $request->get_header( 'X-WP-Nonce' );
271 361
272 362 // Verify the nonce.
273 363 if ( ! wp_verify_nonce( sanitize_text_field( (string) $nonce ), 'wp_rest' ) ) {
274 - wp_send_json_error(
275 - array(
276 - 'data' => __( 'Nonce verification failed.', 'nps-survey' ),
277 - 'status' => false,
278 -
279 - )
364 + return new \WP_Error(
365 + 'nonce_verification_failed',
366 + __( 'Nonce verification failed.', 'nps-survey' ),
367 + array( 'status' => 403 )
280 368 );
281 369 }
282 370
283 371 $current_user = wp_get_current_user();
372 + $raw_nps_id = $request->get_param( 'nps_id' );
373 + $raw_rating = $request->get_param( 'rating' );
374 + $raw_comment = $request->get_param( 'comment' );
375 + $raw_slug = $request->get_param( 'plugin_slug' );
376 + $nps_id = sanitize_key( is_string( $raw_nps_id ) ? $raw_nps_id : '' );
377 + $rating = absint( is_numeric( $raw_rating ) ? $raw_rating : 0 );
378 + $comment = sanitize_text_field( is_string( $raw_comment ) ? $raw_comment : '' );
379 + $plugin_slug = sanitize_key( is_string( $raw_slug ) ? $raw_slug : '' );
284 380
285 381 /**
286 382 * Filter the post data.
287 383 * This can be used to modify the post data before sending it to the API.
@@ -286,21 +382,23 @@
286 382 * Filter the post data.
287 383 * This can be used to modify the post data before sending it to the API.
288 384 *
289 385 * @param array<mixed> $post_data Post data.
386 + * @param string $nps_id NPS ID.
290 387 * @return array<mixed>
291 388 */
292 389 $post_data = apply_filters(
293 390 'nps_survey_post_data',
294 391 array(
295 - 'rating' => ! empty( $request['rating'] ) ? sanitize_text_field( strval( $request['rating'] ) ) : '',
296 - 'comment' => ! empty( $request['comment'] ) ? sanitize_text_field( strval( $request['comment'] ) ) : '',
392 + 'rating' => $rating,
393 + 'comment' => $comment,
297 394 'email' => $current_user->user_email,
298 - 'first_name' => $current_user->first_name ?? $current_user->display_name,
299 - 'last_name' => $current_user->last_name ?? '',
300 - 'source' => ! empty( $request['plugin_slug'] ) ? sanitize_text_field( strval( $request['plugin_slug'] ) ) : '',
301 - 'plugin_slug' => ! empty( $request['plugin_slug'] ) ? sanitize_text_field( strval( $request['plugin_slug'] ) ) : '',
302 - )
395 + 'first_name' => ! empty( $current_user->first_name ) ? $current_user->first_name : $current_user->display_name,
396 + 'last_name' => ! empty( $current_user->last_name ) ? $current_user->last_name : '',
397 + 'source' => $plugin_slug,
398 + 'plugin_slug' => $plugin_slug,
399 + ),
400 + $nps_id
303 401 );
304 402
305 403 /**
306 404 * Filter the API endpoint.
@@ -306,8 +404,9 @@
306 404 * Filter the API endpoint.
307 405 *
308 406 * @param string $api_endpoint API endpoint.
309 407 * @param array<mixed> $post_data Post data.
408 + * @param string $nps_id NPS ID.
310 409 *
311 410 * @return string
312 411 */
313 412 $api_endpoint = apply_filters(
@@ -312,9 +411,10 @@
312 411 */
313 412 $api_endpoint = apply_filters(
314 413 'nps_survey_api_endpoint',
315 414 self::get_api_domain() . 'wp-json/bsf-metrics-server/v1/nps-survey/',
316 - $post_data // Pass the post data to the filter, so that the endpoint can be modified based on the data.
415 + $post_data, // Pass the post data to the filter, so that the endpoint can be modified based on the data.
416 + $nps_id
317 417 );
318 418
319 419 $post_data_in_json = wp_json_encode( $post_data );
320 420 $request_args = array(
@@ -325,22 +425,28 @@
325 425
326 426 $response = wp_safe_remote_post( $api_endpoint, $request_args );
327 427
328 428 if ( is_wp_error( $response ) ) {
329 - // There was an error in the request.
330 - wp_send_json_error(
331 - array(
332 - 'data' => 'Failed ' . $response->get_error_message(),
333 - 'status' => false,
334 -
335 - )
429 + return new \WP_Error(
430 + 'remote_request_failed',
431 + __( 'Remote request failed.', 'nps-survey' ),
432 + array( 'status' => 500 )
336 433 );
337 434 }
338 435
339 436 $response_code = wp_remote_retrieve_response_code( $response );
340 437
341 - if ( 200 === $response_code ) {
438 + if ( 200 === $response_code || 201 === $response_code ) {
342 439
440 + // If the status update should be skipped, return success.
441 + if ( self::should_skip_status_update( $nps_id, 'submit', $post_data ) ) {
442 + return rest_ensure_response(
443 + array(
444 + 'status' => true,
445 + )
446 + );
447 + }
448 +
343 449 $nps_form_status = array(
344 450 'dismiss_count' => 0,
345 451 'dismiss_permanently' => true,
346 452 'dismiss_step' => '',
@@ -345,11 +451,11 @@
345 451 'dismiss_permanently' => true,
346 452 'dismiss_step' => '',
347 453 );
348 454
349 - update_option( self::get_nps_id( strval( $request['plugin_slug'] ) ), $nps_form_status, false );
455 + update_option( self::get_nps_id( $plugin_slug ), $nps_form_status, false );
350 456
351 - wp_send_json_success(
457 + return rest_ensure_response(
352 458 array(
353 459 'status' => true,
354 460 )
355 461 );
@@ -354,13 +460,12 @@
354 460 )
355 461 );
356 462
357 463 } else {
358 - wp_send_json_error(
359 - array(
360 - 'status' => false,
361 -
362 - )
464 + return new \WP_Error(
465 + 'api_error',
466 + __( 'Request failed.', 'nps-survey' ),
467 + array( 'status' => 500 )
363 468 );
364 469 }
365 470 }
366 471
@@ -366,11 +471,10 @@
366 471
367 472 /**
368 473 * Dismiss NPS Survey.
369 474 *
370 - * @param \WP_REST_Request $request Request object.
371 - * @return void
372 - * @phpstan-ignore-next-line
475 + * @param \WP_REST_Request<array<string,mixed>> $request Request object.
476 + * @return \WP_REST_Response|\WP_Error
373 477 */
374 478 public static function dismiss_nps_survey_panel( $request ) {
375 479
376 480 $nonce = $request->get_header( 'X-WP-Nonce' );
@@ -376,21 +480,37 @@
376 480 $nonce = $request->get_header( 'X-WP-Nonce' );
377 481
378 482 // Verify the nonce.
379 483 if ( ! wp_verify_nonce( sanitize_text_field( (string) $nonce ), 'wp_rest' ) ) {
380 - wp_send_json_error(
484 + return new \WP_Error(
485 + 'nonce_verification_failed',
486 + __( 'Nonce verification failed.', 'nps-survey' ),
487 + array( 'status' => 403 )
488 + );
489 + }
490 +
491 + // If the status update should be skipped, return success.
492 + $raw_nps_id = $request->get_param( 'nps_id' );
493 + $raw_slug = $request->get_param( 'plugin_slug' );
494 + $raw_timespan = $request->get_param( 'dismiss_timespan' );
495 + $raw_step = $request->get_param( 'current_step' );
496 + $nps_id = sanitize_key( is_string( $raw_nps_id ) ? $raw_nps_id : '' );
497 + $plugin_slug = sanitize_key( is_string( $raw_slug ) ? $raw_slug : '' );
498 + $dismiss_timespan = absint( is_numeric( $raw_timespan ) ? $raw_timespan : 0 );
499 + $current_step = sanitize_text_field( is_string( $raw_step ) ? $raw_step : '' );
500 +
501 + if ( self::should_skip_status_update( $nps_id, 'dismiss' ) ) {
502 + return rest_ensure_response(
381 503 array(
382 - 'data' => __( 'Nonce verification failed.', 'nps-survey' ),
383 - 'status' => false,
384 -
504 + 'status' => true,
385 505 )
386 506 );
387 507 }
388 508
389 - $nps_form_status = self::get_nps_survey_dismiss_status( strval( $request['plugin_slug'] ) );
509 + $nps_form_status = self::get_nps_survey_dismiss_status( $plugin_slug );
390 510
391 511 // Add dismiss timespan.
392 - $nps_form_status['dismiss_timespan'] = $request['dismiss_timespan'];
512 + $nps_form_status['dismiss_timespan'] = $dismiss_timespan;
393 513
394 514 // Add dismiss date.
395 515 $nps_form_status['dismiss_time'] = time();
396 516
@@ -395,9 +515,9 @@
395 515 $nps_form_status['dismiss_time'] = time();
396 516
397 517 // Update dismiss count.
398 518 $nps_form_status['dismiss_count'] += 1;
399 - $nps_form_status['dismiss_step'] = $request['current_step'];
519 + $nps_form_status['dismiss_step'] = $current_step;
400 520
401 521 // Dismiss Permanantly.
402 522 if ( $nps_form_status['dismiss_count'] >= 2 ) {
403 523 $nps_form_status['dismiss_permanently'] = true;
@@ -402,11 +522,11 @@
402 522 if ( $nps_form_status['dismiss_count'] >= 2 ) {
403 523 $nps_form_status['dismiss_permanently'] = true;
404 524 }
405 525
406 - update_option( self::get_nps_id( strval( $request['plugin_slug'] ) ), $nps_form_status );
526 + update_option( self::get_nps_id( $plugin_slug ), $nps_form_status, false );
407 527
408 - wp_send_json_success(
528 + return rest_ensure_response(
409 529 array(
410 530 'status' => true,
411 531 )
412 532 );
@@ -493,8 +613,23 @@
493 613 }
494 614 }
495 615
496 616 return true;
617 + }
618 +
619 + /**
620 + * Check if NPS Survey is enabled for admin only. Default is true.
621 + *
622 + * @since 1.0.13
623 + * @return bool
624 + */
625 + public static function is_nps_survey_enabled_for_admin_only() {
626 + /**
627 + * Filter to check if NPS Survey is enabled for admin only.
628 + *
629 + * @since 1.0.13
630 + */
631 + return apply_filters( 'nps_survey_enabled_for_admin_only', true );
497 632 }
498 633
499 634 /**
500 635 * Get NPS Dismiss Option Name.