PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress / 5.2.11
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress v5.2.11
5.6.8 5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / kit / nps-survey / classes / nps-survey-script.php
latepoint / lib / kit / nps-survey / classes Last commit date
nps-survey-script.php 4 months ago
nps-survey-script.php
606 lines
1 <?php
2 /**
3 * NPS Survey Script
4 * File to handle behaviour and content of NPS popup`
5 *
6 * @package {{package}}
7 */
8
9 // Prevent multiple inclusions of this file.
10 if ( defined( 'NPS_SURVEY_SCRIPT_LOADED' ) ) {
11 return;
12 }
13 define( 'NPS_SURVEY_SCRIPT_LOADED', true );
14
15 /**
16 * Nps_Survey
17 */
18 class Nps_Survey {
19 /**
20 * Instance
21 *
22 * @access private
23 * @var object Class Instance.
24 * @since 1.0.0
25 */
26 private static $instance = null;
27
28 /**
29 * Constructor.
30 *
31 * @since 1.0.0
32 */
33 public function __construct() {
34 add_action( 'rest_api_init', array( $this, 'register_route' ) );
35 }
36
37 /**
38 * Initiator
39 *
40 * @since 1.0.0
41 * @return object initialized object of class.
42 */
43 public static function get_instance() {
44 if ( null === self::$instance ) {
45 self::$instance = new self();
46 }
47 return self::$instance;
48 }
49
50 /**
51 * Render NPS Survey.
52 *
53 * @param string $id ID of the root element, should start with nps-survey- .
54 * @param array<mixed> $vars Variables to be passed to the NPS.
55 * @since 1.0.0
56 * @return void
57 */
58 public static function show_nps_notice( string $id, array $vars = [] ): void {
59
60 if ( ! isset( $vars['plugin_slug'] ) || ! is_string( $vars['plugin_slug'] ) ) {
61 return;
62 }
63
64 $plugin_slug = $vars['plugin_slug'];
65 $display_after = is_int( $vars['display_after'] ) ? $vars['display_after'] : 0;
66
67 /**
68 * Filter to check if the NPS survey should be shown.
69 *
70 * @param bool $status Whether to show the notice.
71 * @param string $plugin_slug Plugin slug.
72 * @since 1.0.13
73 */
74 $show_notice = apply_filters(
75 'nps_survey_show_notice',
76 self::is_show_nps_survey_form( $plugin_slug, $display_after ),
77 $plugin_slug
78 );
79
80 if ( ! $show_notice ) {
81 return;
82 }
83
84 $show_on_screen = ! empty( $vars['show_on_screens'] ) && is_array( $vars['show_on_screens'] ) ? $vars['show_on_screens'] : [ 'dashboard' ];
85
86 if ( ! function_exists( 'get_current_screen' ) ) {
87 require_once ABSPATH . '/wp-admin/includes/screen.php';
88 }
89 $current_screen = get_current_screen();
90
91 $admin_only = self::is_nps_survey_enabled_for_admin_only();
92 if ( $admin_only && $current_screen instanceof WP_Screen && ! in_array( $current_screen->id, $show_on_screen, true ) ) {
93 return;
94 }
95 // Loading script here to confirm if the screen is allowed or not.
96 self::editor_load_scripts( $show_on_screen );
97
98 ?><div data-id="<?php echo esc_attr( $id ); ?>" class="nps-survey-root" data-vars="<?php echo esc_attr( strval( wp_json_encode( $vars ) ) ); ?>"></div>
99 <?php
100 }
101
102 /**
103 * Generate and return the Google fonts url.
104 *
105 * @since 1.0.2
106 * @return string
107 */
108 public static function google_fonts_url() {
109
110 $font_families = array(
111 'Figtree:400,500,600,700',
112 );
113
114 $query_args = array(
115 'family' => rawurlencode( implode( '|', $font_families ) ),
116 'subset' => rawurlencode( 'latin,latin-ext' ),
117 );
118
119 return add_query_arg( $query_args, '//fonts.googleapis.com/css' );
120 }
121
122 /**
123 * Load script.
124 *
125 * @param array<string> $show_on_screens An array of screen IDs where the scripts should be loaded.
126 * @since 1.0.0
127 * @return void
128 */
129 public static function editor_load_scripts( $show_on_screens ): void {
130
131 $admin_only = self::is_nps_survey_enabled_for_admin_only();
132 if ( $admin_only && ! is_admin() ) {
133 return;
134 }
135
136 $screen = get_current_screen();
137 $screen_id = $screen ? $screen->id : '';
138
139 if ( $admin_only && ! in_array( $screen_id, $show_on_screens, true ) ) {
140 return;
141 }
142
143 $handle = 'nps-survey-script';
144 $build_path = NPS_SURVEY_DIR . 'dist/';
145 $default_build_url = NPS_SURVEY_URL . 'dist/';
146
147 // Use a filter to allow $build_url to be modified externally.
148 $build_url = apply_filters( 'nps_survey_build_url', $default_build_url );
149 $script_asset_path = $build_path . 'main.asset.php';
150
151 $script_info = file_exists( $script_asset_path )
152 ? include $script_asset_path
153 : array(
154 'dependencies' => array(),
155 'version' => NPS_SURVEY_VER,
156 );
157
158 $script_dep = array_merge( $script_info['dependencies'], array( 'jquery' ) );
159
160 wp_enqueue_script(
161 $handle,
162 $build_url . 'main.js',
163 $script_dep,
164 $script_info['version'],
165 true
166 );
167
168 $data = apply_filters(
169 'nps_survey_vars',
170 [
171 'ajaxurl' => esc_url( admin_url( 'admin-ajax.php' ) ),
172 '_ajax_nonce' => wp_create_nonce( 'nps-survey' ),
173 'rest_api_nonce' => current_user_can( 'manage_options' ) ? wp_create_nonce( 'wp_rest' ) : '',
174 ]
175 );
176
177 // Add localize JS.
178 wp_localize_script(
179 'nps-survey-script',
180 'npsSurvey',
181 $data
182 );
183
184 wp_enqueue_style( 'nps-survey-style', $build_url . '/style-main.css', array(), NPS_SURVEY_VER );
185 wp_style_add_data( 'nps-survey-style', 'rtl', 'replace' );
186 wp_enqueue_style( 'nps-survey-google-fonts', self::google_fonts_url(), array(), 'all' );
187 }
188
189 /**
190 * Load all the required files in the importer.
191 *
192 * @since 1.0.0
193 * @return void
194 */
195 public static function register_route(): void {
196
197 register_rest_route(
198 self::get_api_namespace(),
199 '/rating/',
200 array(
201 array(
202 'methods' => \WP_REST_Server::CREATABLE,
203 'callback' => array( self::class, 'submit_rating' ),
204 'permission_callback' => array( self::class, 'get_item_permissions_check' ),
205 'args' => array(),
206 ),
207 )
208 );
209
210 register_rest_route(
211 self::get_api_namespace(),
212 '/dismiss-nps-survey/',
213 array(
214 array(
215 'methods' => \WP_REST_Server::CREATABLE,
216 'callback' => array( self::class, 'dismiss_nps_survey_panel' ),
217 'permission_callback' => array( self::class, 'get_item_permissions_check' ),
218 'args' => array(),
219 ),
220 )
221 );
222 }
223
224 /**
225 * Get the API URL.
226 *
227 * @since 1.0.0
228 *
229 * @return string
230 */
231 public static function get_api_domain() {
232 return trailingslashit( defined( 'NPS_SURVEY_REMOTE_URL' ) ? NPS_SURVEY_REMOTE_URL : apply_filters( 'nps_survey_api_domain', 'https://metrics.brainstormforce.com/' ) );
233 }
234
235 /**
236 * Get api namespace
237 *
238 * @since 1.0.0
239 * @return string
240 */
241 public static function get_api_namespace() {
242 return 'nps-survey/v1';
243 }
244
245 /**
246 * Get API headers
247 *
248 * @since 1.0.0
249 * @return array<string, string>
250 */
251 public static function get_api_headers() {
252 return array(
253 'Content-Type' => 'application/json',
254 'Accept' => 'application/json',
255 );
256 }
257
258 /**
259 * Check whether a given request has permission to read notes.
260 *
261 * @param object $request WP_REST_Request Full details about the request.
262 * @return object|bool
263 */
264 public static function get_item_permissions_check( $request ) {
265 /**
266 * Filter to check if NPS Survey is enabled on API.
267 *
268 * @since 1.0.13
269 */
270 if ( apply_filters( 'nps_survey_api_disable_permission_check', false ) ) {
271 return true;
272 }
273
274 if ( ! current_user_can( 'manage_options' ) ) {
275 return new \WP_Error(
276 'gt_rest_cannot_access',
277 __( 'Sorry, you are not allowed to do that.', 'nps-survey' ),
278 array( 'status' => rest_authorization_required_code() )
279 );
280 }
281 return true;
282 }
283
284 /**
285 * Method to determine if the NPS survey status update should be skipped for database option.
286 *
287 * @param string $nps_id NPS ID.
288 * @param string $type Type of action (e.g., 'submit', 'dismiss').
289 * @param array $data Additional data related to the NPS survey.
290 *
291 * @since 1.0.13
292 * @return bool
293 * @phpstan-ignore-next-line
294 */
295 public static function should_skip_status_update( $nps_id, $type, $data = array() ): bool {
296 /**
297 * Filter to determine if the NPS survey status should be updated.
298 *
299 * @param bool $update Default is true, can be modified by the filter.
300 * @param array $post_data Post data being sent.
301 * @since 1.0.13
302 */
303 return apply_filters(
304 'nps_survey_should_skip_status_update',
305 false, // Default to false, can be modified by the filter.
306 array_merge(
307 $data,
308 array(
309 'nps_id' => $nps_id,
310 'action_type' => $type,
311 )
312 )
313 );
314 }
315
316 /**
317 * Submit Ratings.
318 *
319 * @param \WP_REST_Request $request Request object.
320 * @return void
321 * @phpstan-ignore-next-line
322 */
323 public static function submit_rating( $request ) {
324
325 $nonce = $request->get_header( 'X-WP-Nonce' );
326
327 // Verify the nonce.
328 if ( ! wp_verify_nonce( sanitize_text_field( (string) $nonce ), 'wp_rest' ) ) {
329 wp_send_json_error(
330 array(
331 'data' => __( 'Nonce verification failed.', 'nps-survey' ),
332 'status' => false,
333
334 )
335 );
336 }
337
338 $current_user = wp_get_current_user();
339 $nps_id = $request->get_param( 'nps_id' ) ?? '';
340
341 /**
342 * Filter the post data.
343 * This can be used to modify the post data before sending it to the API.
344 *
345 * @param array<mixed> $post_data Post data.
346 * @param string $nps_id NPS ID.
347 * @return array<mixed>
348 */
349 $post_data = apply_filters(
350 'nps_survey_post_data',
351 array(
352 'rating' => ! empty( $request['rating'] ) ? sanitize_text_field( strval( $request['rating'] ) ) : '',
353 'comment' => ! empty( $request['comment'] ) ? sanitize_text_field( strval( $request['comment'] ) ) : '',
354 'email' => $current_user->user_email,
355 'first_name' => $current_user->first_name ?? $current_user->display_name,
356 'last_name' => $current_user->last_name ?? '',
357 'source' => ! empty( $request['plugin_slug'] ) ? sanitize_text_field( strval( $request['plugin_slug'] ) ) : '',
358 'plugin_slug' => ! empty( $request['plugin_slug'] ) ? sanitize_text_field( strval( $request['plugin_slug'] ) ) : '',
359 ),
360 $nps_id
361 );
362
363 /**
364 * Filter the API endpoint.
365 *
366 * @param string $api_endpoint API endpoint.
367 * @param array<mixed> $post_data Post data.
368 * @param string $nps_id NPS ID.
369 *
370 * @return string
371 */
372 $api_endpoint = apply_filters(
373 'nps_survey_api_endpoint',
374 self::get_api_domain() . 'wp-json/bsf-metrics-server/v1/nps-survey/',
375 $post_data, // Pass the post data to the filter, so that the endpoint can be modified based on the data.
376 $nps_id
377 );
378
379 $post_data_in_json = wp_json_encode( $post_data );
380 $request_args = array(
381 'body' => $post_data_in_json ? $post_data_in_json : '',
382 'headers' => self::get_api_headers(),
383 'timeout' => 60,
384 );
385
386 $response = wp_safe_remote_post( $api_endpoint, $request_args );
387
388 if ( is_wp_error( $response ) ) {
389 // There was an error in the request.
390 wp_send_json_error(
391 array(
392 'data' => 'Failed ' . $response->get_error_message(),
393 'status' => false,
394 )
395 );
396 }
397
398 $response_code = wp_remote_retrieve_response_code( $response );
399
400 if ( 200 === $response_code || 201 === $response_code ) {
401
402 // If the status update should be skipped, return success.
403 if ( self::should_skip_status_update( $nps_id, 'submit', $post_data ) ) {
404 wp_send_json_success(
405 array(
406 'status' => true,
407 )
408 );
409 }
410
411 $nps_form_status = array(
412 'dismiss_count' => 0,
413 'dismiss_permanently' => true,
414 'dismiss_step' => '',
415 );
416
417 update_option( self::get_nps_id( strval( $request['plugin_slug'] ) ), $nps_form_status, false );
418
419 wp_send_json_success(
420 array(
421 'status' => true,
422 )
423 );
424
425 } else {
426 wp_send_json_error(
427 array(
428 'status' => false,
429 )
430 );
431 }
432 }
433
434 /**
435 * Dismiss NPS Survey.
436 *
437 * @param \WP_REST_Request $request Request object.
438 * @return void
439 * @phpstan-ignore-next-line
440 */
441 public static function dismiss_nps_survey_panel( $request ) {
442
443 $nonce = $request->get_header( 'X-WP-Nonce' );
444
445 // Verify the nonce.
446 if ( ! wp_verify_nonce( sanitize_text_field( (string) $nonce ), 'wp_rest' ) ) {
447 wp_send_json_error(
448 array(
449 'data' => __( 'Nonce verification failed.', 'nps-survey' ),
450 'status' => false,
451
452 )
453 );
454 }
455
456 // If the status update should be skipped, return success.
457 $nps_id = $request->get_param( 'nps_id' ) ?? '';
458 if ( self::should_skip_status_update( $nps_id, 'dismiss' ) ) {
459 wp_send_json_success(
460 array(
461 'status' => true,
462 )
463 );
464 }
465
466 $nps_form_status = self::get_nps_survey_dismiss_status( strval( $request['plugin_slug'] ) );
467
468 // Add dismiss timespan.
469 $nps_form_status['dismiss_timespan'] = $request['dismiss_timespan'];
470
471 // Add dismiss date.
472 $nps_form_status['dismiss_time'] = time();
473
474 // Update dismiss count.
475 $nps_form_status['dismiss_count'] += 1;
476 $nps_form_status['dismiss_step'] = $request['current_step'];
477
478 // Dismiss Permanantly.
479 if ( $nps_form_status['dismiss_count'] >= 2 ) {
480 $nps_form_status['dismiss_permanently'] = true;
481 }
482
483 update_option( self::get_nps_id( strval( $request['plugin_slug'] ) ), $nps_form_status );
484
485 wp_send_json_success(
486 array(
487 'status' => true,
488 )
489 );
490 }
491
492 /**
493 * Get dismiss status of NPS Survey.
494 *
495 * @param string $plugin_slug slug of unique NPS Survey.
496 * @return array<string, mixed>
497 */
498 public static function get_nps_survey_dismiss_status( string $plugin_slug ) {
499
500 $default_status = get_option(
501 self::get_nps_id( $plugin_slug ),
502 array(
503 'dismiss_count' => 0,
504 'dismiss_permanently' => false,
505 'dismiss_step' => '',
506 'dismiss_time' => '',
507 'dismiss_timespan' => null,
508 'first_render_time' => null,
509 )
510 );
511
512 if ( ! is_array( $default_status ) ) {
513 return array();
514 }
515
516 return array(
517 'dismiss_count' => ! empty( $default_status['dismiss_count'] ) ? $default_status['dismiss_count'] : 0,
518 'dismiss_permanently' => ! empty( $default_status['dismiss_permanently'] ) ? $default_status['dismiss_permanently'] : false,
519 'dismiss_step' => ! empty( $default_status['dismiss_step'] ) ? $default_status['dismiss_step'] : '',
520 'dismiss_time' => ! empty( $default_status['dismiss_time'] ) ? $default_status['dismiss_time'] : '',
521 'dismiss_timespan' => ! empty( $default_status['dismiss_timespan'] ) ? $default_status['dismiss_timespan'] : null,
522 'first_render_time' => ! empty( $default_status['first_render_time'] ) ? $default_status['first_render_time'] : null,
523 );
524 }
525
526 /**
527 * Show status of NPS Survey.
528 *
529 * @param string $plugin_slug slug of unique NPS Survey.
530 * @param int $display_after number of days after which NPS Survey should be displayed.
531 * @return bool
532 */
533 public static function is_show_nps_survey_form( string $plugin_slug, int $display_after ) {
534
535 $current_time = time();
536 $status = self::get_nps_survey_dismiss_status( $plugin_slug );
537
538 if ( $status['dismiss_permanently'] ) {
539 return false;
540 }
541
542 $first_render_time = $status['first_render_time'];
543
544 if ( 0 !== $display_after ) {
545 if ( null === $first_render_time ) {
546 $status['first_render_time'] = $current_time;
547 update_option( self::get_nps_id( $plugin_slug ), $status );
548 $status = self::get_nps_survey_dismiss_status( $plugin_slug );
549 return false;
550 }
551 if ( $display_after + $first_render_time > $current_time ) {
552 return false;
553 }
554 }
555
556 // Retrieve the stored date time stamp from wp_options.
557 $stored_date_timestamp = $status['dismiss_time'];
558 $dismiss_timespan = $status['dismiss_timespan'];
559
560 if ( $stored_date_timestamp ) {
561
562 $current_time = time();
563
564 // time difference of current time and the time user dismissed the nps.
565 $time_difference = $current_time - $stored_date_timestamp;
566
567 // Check if two weeks have passed.
568 if ( $time_difference <= $dismiss_timespan ) {
569 return false;
570 }
571 }
572
573 return true;
574 }
575
576 /**
577 * Check if NPS Survey is enabled for admin only. Default is true.
578 *
579 * @since 1.0.13
580 * @return bool
581 */
582 public static function is_nps_survey_enabled_for_admin_only() {
583 /**
584 * Filter to check if NPS Survey is enabled for admin only.
585 *
586 * @since 1.0.13
587 */
588 return apply_filters( 'nps_survey_enabled_for_admin_only', true );
589 }
590
591 /**
592 * Get NPS Dismiss Option Name.
593 *
594 * @param string $plugin_slug Plugin name.
595 * @return string
596 */
597 public static function get_nps_id( $plugin_slug ) {
598 return 'nps-survey-' . $plugin_slug;
599 }
600 }
601
602 /**
603 * Kicking this off by calling 'get_instance()' method
604 */
605 Nps_Survey::get_instance();
606