PluginProbe
UseStrict's Calendly Embedder / trunk
UseStrict's Calendly Embedder vtrunk
trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.6.1 1.1.6.2 1.1.7 1.1.7.1 1.1.7.2 1.2 1.2.1
cal-embedder-lite / cal-embedder-lite.php

cal-embedder-lite.php in UseStrict's Calendly Embedder trunk, at cal-embedder-lite.php

875 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Initialize the main plugin file.
4 *
5 * @category Class
6 * @package Wp_Cal_Embed_Lite
7 * @author Vinny Alves
8 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
9 * @link https://usestrict.net
10 */
11
12 //phpcs:disable WordPress.Files.FileName
13
14 defined( 'ABSPATH' ) || die( 'No direct access allowed' );
15
16 /**
17 * Plugin Name: UseStrict's Calendly Embedder
18 * Plugin URI: https://usestrict.net/cal-embedder-pro
19 * Description: Simple embedding for Calendly (and soon various other calendar services).
20 * Author: Vinny Alves
21 * Author URI: https://usestrict.consulting
22 * Text Domain: cal-embedder-lite
23 * Domain Path: /language
24 * Version: 1.2.1
25 *
26 * @package Wp_Cal_Embed_Lite
27 */
28
29 if ( ! class_exists( 'Wp_Cal_Embed_Lite' ) ) :
30
31 /**
32 * This is the main plugin class.
33 *
34 * @package Wp_Cal_Embed_Lite
35 */
36 class Wp_Cal_Embed_Lite {
37
38 /**
39 * VERSION constant
40 *
41 * @var string
42 */
43 const VERSION = '1.2.1';
44
45 /**
46 * Holds our environment variables.
47 *
48 * @var object
49 */
50 private $environment;
51
52
53 /**
54 * Calendly API URL v1
55 *
56 * @var string
57 */
58 private $calendly_api_url_v1 = 'https://calendly.com/api/v1';
59
60 /**
61 * Calendly API URL v2
62 *
63 * @var string
64 */
65 private $calendly_api_url_v2 = 'https://api.calendly.com/';
66
67 /**
68 * The key of the transient which stores Calendly data
69 *
70 * @var string
71 */
72 private static $transient = 'wpcalel-user-data';
73
74 /**
75 * Our settings name.
76 *
77 * @var string
78 */
79 private $settings_name = __CLASS__;
80
81 /**
82 * Holds the plugin settings
83 *
84 * @var object
85 */
86 public $settings;
87
88
89
90 /**
91 * Dummy constructor.
92 */
93 private function __construct() {
94 /* do nothing */ }
95
96
97
98 /**
99 * Singleton.
100 *
101 * @return Wp_Cal_Embed_Lite
102 */
103 public static function instance() {
104 static $instance = null;
105
106 if ( null === $instance ) {
107 $instance = new self();
108 $instance->setup_environment();
109 $instance->get_settings();
110 $instance->add_actions();
111 }
112
113 return $instance;
114 }
115
116
117 /**
118 * Sets up our environment.
119 */
120 private function setup_environment() {
121 $this->environment = (object) array(
122 'js_url' => plugins_url( 'assets/js', __FILE__ ),
123 'css_url' => plugins_url( 'assets/css', __FILE__ ),
124 'plugin_file' => plugin_dir_path( __FILE__ ),
125 'plugin_basename' => plugin_basename( __FILE__ ),
126 );
127 }
128
129 /**
130 * Gets the settings from the database.
131 */
132 private function get_settings() {
133 if ( is_admin() ) {
134 $this->settings = (object) get_option( __CLASS__, array() );
135 }
136 }
137
138 /**
139 * Add actions.
140 */
141 private function add_actions() {
142 add_action( 'init', array( $this, 'load_textdomain' ) );
143 add_action( 'init', array( $this, 'add_shortcode' ) );
144 add_action( 'wp_ajax_wpcalel-userinfo', array( $this, 'ajax_get_user_info' ) );
145
146 // Register menu if Pro is not installed.
147 if ( false === has_filter( 'wpcalep-handler' ) ) {
148 add_action( 'admin_menu', array( $this, 'add_options_page' ) );
149 add_action( 'admin_init', array( $this, 'register_setting' ) );
150 }
151 }
152
153
154 /**
155 * Load i18n.
156 */
157 public function load_textdomain() {
158 load_plugin_textdomain( 'cal-embedder-lite', false, dirname( untrailingslashit( plugin_basename( __FILE__ ) ) ) . '/language' );
159 }
160
161
162 /**
163 * Adds the shortcode support.
164 */
165 public function add_shortcode() {
166 add_shortcode( 'wpcalel', array( $this, 'wpcalel_shortcode' ) );
167 }
168
169
170 /**
171 * Shortcode handler.
172 *
173 * @param array $atts The shortcode attributes.
174 * @param mixed NULL|string $content The shortcode content.
175 * @return string
176 */
177 public function wpcalel_shortcode( $atts = array(), $content = null ) {
178 $a = shortcode_atts(
179 array(
180 'type' => 'calendly',
181 'widget' => 'inline', // inline, popup, or link.
182 'url' => 'url',
183 ),
184 $atts,
185 'cal-embedder-lite'
186 );
187
188 if ( empty( $a['url'] ) ) {
189 return __( 'You MUST provide a URL for the Calendly shortcode', 'cal-embedder-lite' );
190 }
191
192 $type = sanitize_text_field( $a['type'] );
193 $widget = sanitize_text_field( $a['widget'] );
194
195 // Shortcircuit if we have pro handlers.
196 if ( false !== has_filter( 'wpcalep_handler' ) ) {
197 return apply_filters( 'wpcalep_handler', $atts, $content ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
198 }
199
200 if ( ! method_exists( $this, "{$type}_{$widget}_shortcode" ) ) {
201 /* translators: 1: the type of shortcode 2: the widget type */
202 return sprintf( esc_html__( 'I do not know how to handle these attributes. type: "%1$s", widget: "%2$s"', 'cal-embedder-lite' ), $type, $widget );
203 }
204
205 static $registered_scripts = null;
206 if ( null === $registered_scripts ) {
207 wp_enqueue_style( 'wpcalel-calendly', 'https://calendly.com/assets/external/widget.css', array(), self::VERSION );
208 wp_enqueue_script( 'wpcalel-calendly', 'https://assets.calendly.com/assets/external/widget.js', array(), self::VERSION, $in_footer = true );
209 wp_enqueue_script( 'wpcalel-calendly-handler', $this->environment->js_url . '/calendly.js', array( 'jquery', 'wpcalel-calendly' ), self::VERSION, $in_footer = true );
210 wp_localize_script(
211 'wpcalel-calendly-handler',
212 'wpcalel',
213 array(
214 'ajax_url' => admin_url( 'admin-ajax.php' ),
215 'nonce' => wp_create_nonce( 'wpcalel-calendly' ),
216 )
217 );
218
219 $registered_scripts = true;
220 }
221
222 return call_user_func( array( $this, "{$type}_{$widget}_shortcode" ), $atts, $content );
223 }
224
225
226 /**
227 * Calendly link widget handler.
228 *
229 * @param array $atts The shortcode attributes.
230 * @param mixed NULL|string $content The shortcode content.
231 * @return string
232 */
233 private function calendly_link_shortcode( $atts, $content = null ) {
234 static $count = 0;
235 ++$count;
236
237 $a = shortcode_atts(
238 array(
239 'url' => '',
240
241 // Link Widget settings.
242 'text' => __( 'Schedule time with me', 'cal-embedder-lite' ),
243
244 // Booking page settings.
245 'classes' => '',
246 'styles' => '',
247 'prefill' => false,
248 'query_str' => false,
249 'a1' => '',
250 'a2' => '',
251 'a3' => '',
252 'a4' => '',
253 'a5' => '',
254 'a6' => '',
255 'a7' => '',
256 'a8' => '',
257 'a9' => '',
258 'a10' => '',
259 'hide_gdpr_banner' => false,
260 'hide_landing_page_details' => false,
261 'hide_event_type_details' => false,
262 'background_color' => '',
263 'text_color' => '',
264 'primary_color' => '', // Button and link colors.
265 ),
266 $atts,
267 'cal-embedder-lite'
268 );
269
270 $a['prefill'] = filter_var( $a['prefill'], FILTER_VALIDATE_BOOLEAN );
271 $a['query_str'] = filter_var( $a['query_str'], FILTER_VALIDATE_BOOLEAN );
272 $a['hide_gdpr_banner'] = filter_var( $a['hide_gdpr_banner'], FILTER_VALIDATE_BOOLEAN );
273 $a['hide_landing_page_details'] = filter_var( $a['hide_landing_page_details'], FILTER_VALIDATE_BOOLEAN );
274 $a['hide_event_type_details'] = filter_var( $a['hide_event_type_details'], FILTER_VALIDATE_BOOLEAN );
275
276 // Sanitize/normalize the URL.
277 $parsed = wp_parse_url( $a['url'] );
278 $a['url'] = 'https://calendly.com/' . preg_replace( '@^/+@', '', trailingslashit( $parsed['path'] ) );
279
280 $colors = array();
281 if ( $a['background_color'] ) {
282 $colors['background_color'] = $a['background_color'];
283 }
284 if ( $a['text_color'] ) {
285 $colors['text_color'] = $a['text_color'];
286 }
287 if ( $a['primary_color'] ) {
288 $colors['primary_color'] = $a['primary_color'];
289 }
290
291 if ( ! empty( $colors ) ) {
292 foreach ( $colors as &$color ) {
293 $color = str_replace( '#', '', $color ); // Strip out any # characters.
294 }
295
296 $a['url'] = add_query_arg( $colors, $a['url'] );
297 }
298
299 $hide_fields = array(
300 'hide_gdpr_banner' => $a['hide_gdpr_banner'],
301 'hide_landing_page_details' => $a['hide_landing_page_details'],
302 'hide_event_type_details' => $a['hide_event_type_details'],
303 );
304 $a['url'] = add_query_arg( $hide_fields, $a['url'] );
305
306 // Sanitize the classes (remove dots and normalize the number of spaces between each one).
307 $classes = preg_replace( '/[ ]*\./', ' ', $a['classes'] );
308
309 ob_start();
310 ?>
311 <!-- UseStrict's Calendly Embedder - Calendly link widget start -->
312 <a href="#" id="wpcalel-calendly-link-<?php echo esc_attr( $count ); ?>"
313 class="<?php echo esc_attr( $classes ); ?>"
314 style="<?php echo esc_attr( $a['styles'] ); ?>"
315 data-wpcalel-type="link"
316 data-wpcalel-url="<?php echo esc_url( $a['url'] ); ?>"
317 data-wpcalel-prefill="<?php echo $a['prefill'] ? 'true' : 'false'; ?>"
318 data-wpcalel-query-str="<?php echo $a['query_str'] ? 'true' : 'false'; ?>"
319 >
320 <?php echo esc_html( $a['text'] ); ?>
321 </a>
322 <!-- UseStrict's Calendly Embedder - Calendly link widget end -->
323 <?php
324
325 $content = ob_get_clean();
326
327 return $content;
328 }
329
330
331 /**
332 * Calendly popup widget handler.
333 *
334 * @param array $atts The shortcode attributes.
335 * @param mixed NULL|string $content The shortcode content.
336 * @return string
337 */
338 private function calendly_popup_shortcode( $atts, $content = null ) {
339 static $count = 0;
340 ++$count;
341
342 $a = shortcode_atts(
343 array(
344 'url' => '',
345
346 // Popup Widget settings.
347 'text' => __( 'Schedule time with me', 'cal-embedder-lite' ),
348 'color' => '006bff',
349 'textColor' => 'ffffff',
350 'branding' => false,
351
352 // Booking page settings.
353 'prefill' => false,
354 'query_str' => false,
355 'a1' => '',
356 'a2' => '',
357 'a3' => '',
358 'a4' => '',
359 'a5' => '',
360 'a6' => '',
361 'a7' => '',
362 'a8' => '',
363 'a9' => '',
364 'a10' => '',
365 'hide_gdpr_banner' => false,
366 'hide_landing_page_details' => false,
367 'hide_event_type_details' => false,
368 'background_color' => '',
369 'text_color' => '',
370 'primary_color' => '', // Button and link colors.
371 ),
372 $atts,
373 'cal-embedder-lite'
374 );
375
376 $a['prefill'] = filter_var( $a['prefill'], FILTER_VALIDATE_BOOLEAN );
377 $a['query_str'] = filter_var( $a['query_str'], FILTER_VALIDATE_BOOLEAN );
378 $a['branding'] = filter_var( $a['branding'], FILTER_VALIDATE_BOOLEAN );
379 $a['hide_gdpr_banner'] = filter_var( $a['hide_gdpr_banner'], FILTER_VALIDATE_BOOLEAN );
380 $a['hide_landing_page_details'] = filter_var( $a['hide_landing_page_details'], FILTER_VALIDATE_BOOLEAN );
381 $a['hide_event_type_details'] = filter_var( $a['hide_event_type_details'], FILTER_VALIDATE_BOOLEAN );
382
383 // Sanitize/normalize the URL.
384 $parsed = wp_parse_url( $a['url'] );
385 $a['url'] = 'https://calendly.com/' . preg_replace( '@^/+@', '', trailingslashit( $parsed['path'] ) );
386
387 $button_colors = array();
388 if ( $a['color'] ) {
389 $button_colors['color'] = $a['color'];
390 }
391 if ( $a['textColor'] ) {
392 $button_colors['textColor'] = $a['textColor'];
393 }
394
395 // Normalize # characters.
396 if ( ! empty( $button_colors ) ) {
397 foreach ( $button_colors as $key => $color ) {
398 $color = str_replace( '#', '', $color );
399 $a[ $key ] = '#' . $color;
400 }
401 }
402
403 $colors = array();
404 if ( $a['background_color'] ) {
405 $colors['background_color'] = $a['background_color'];
406 }
407 if ( $a['text_color'] ) {
408 $colors['text_color'] = $a['text_color'];
409 }
410 if ( $a['primary_color'] ) {
411 $colors['primary_color'] = $a['primary_color'];
412 }
413
414 if ( ! empty( $colors ) ) {
415 foreach ( $colors as &$color ) {
416 $color = str_replace( '#', '', $color ); // Strip out any # characters.
417 }
418
419 $a['url'] = add_query_arg( $colors, $a['url'] );
420 }
421
422 $hide_fields = array(
423 'hide_gdpr_banner' => $a['hide_gdpr_banner'],
424 'hide_landing_page_details' => $a['hide_landing_page_details'],
425 'hide_event_type_details' => $a['hide_event_type_details'],
426 );
427 $a['url'] = add_query_arg( $hide_fields, $a['url'] );
428
429 ob_start();
430 ?>
431 <!-- UseStrict's Calendly Embedder - Calendly popup widget start -->
432 <div id="wpcalel-calendly-popup-<?php echo esc_attr( $count ); ?>"
433 data-wpcalel-type="popup"
434 data-wpcalel-url="<?php echo esc_url( $a['url'] ); ?>"
435 data-wpcalel-prefill="<?php echo $a['prefill'] ? 'true' : 'false'; ?>"
436 data-wpcalel-query-str="<?php echo $a['query_str'] ? 'true' : 'false'; ?>"
437 data-wpcalel-text="<?php echo esc_attr( $a['text'] ); ?>"
438 data-wpcalel-color="<?php echo esc_attr( $a['color'] ); ?>"
439 data-wpcalel-textColor="<?php echo esc_attr( $a['textColor'] ); ?>"
440 data-wpcalel-branding="<?php echo $a['branding'] ? 'true' : 'false'; ?>"
441 <?php foreach ( range( 1, 10 ) as $key ) : ?>
442 <?php if ( ! empty( $a[ 'a' . $key ] ) ) : ?>
443 data-wpcalel-<?php echo esc_attr( 'a' . $key ); ?>="<?php echo esc_attr( $a[ 'a' . $key ] ); ?>"
444 <?php endif; ?>
445 <?php endforeach; ?>
446 ></div>
447 <!-- UseStrict's Calendly Embedder - Calendly popup widget end -->
448
449 <?php
450
451 $content = ob_get_clean();
452
453 return $content;
454 }
455
456 /**
457 * Calendly Inline shortcode handler.
458 *
459 * @see https://help.calendly.com/hc/en-us/articles/360020052833-Advanced-embed-options
460 * @param array $atts The shortcode attributes.
461 * @param mixed NULL|string $content The shortcode content.
462 * @return string
463 */
464 private function calendly_inline_shortcode( $atts, $content = null ) {
465 static $count = 0;
466 ++$count;
467
468 $a = shortcode_atts(
469 array(
470 'url' => '',
471
472 // Booking page settings.
473 'prefill' => false,
474 'query_str' => false,
475 'min-width' => '320px',
476 'height' => '650px',
477 'classes' => '',
478 'styles' => 'overflow-x:hidden;overflow-y:hidden',
479 'a1' => '',
480 'a2' => '',
481 'a3' => '',
482 'a4' => '',
483 'a5' => '',
484 'a6' => '',
485 'a7' => '',
486 'a8' => '',
487 'a9' => '',
488 'a10' => '',
489 'hide_gdpr_banner' => false,
490 'hide_landing_page_details' => false,
491 'hide_event_type_details' => false,
492 'background_color' => '',
493 'text_color' => '',
494 'primary_color' => '', // Button and link colors.
495 ),
496 $atts,
497 'cal-embedder-lite'
498 );
499
500 $a['prefill'] = filter_var( $a['prefill'], FILTER_VALIDATE_BOOLEAN );
501 $a['query_str'] = filter_var( $a['query_str'], FILTER_VALIDATE_BOOLEAN );
502 $a['hide_gdpr_banner'] = filter_var( $a['hide_gdpr_banner'], FILTER_VALIDATE_BOOLEAN );
503 $a['hide_landing_page_details'] = filter_var( $a['hide_landing_page_details'], FILTER_VALIDATE_BOOLEAN );
504 $a['hide_event_type_details'] = filter_var( $a['hide_event_type_details'], FILTER_VALIDATE_BOOLEAN );
505
506 // Sanitize/normalize the URL.
507 $parsed = wp_parse_url( $a['url'] );
508 $a['url'] = 'https://calendly.com/' . preg_replace( '@^/+@', '', trailingslashit( $parsed['path'] ) );
509
510 $colors = array();
511 if ( $a['background_color'] ) {
512 $colors['background_color'] = $a['background_color'];
513 }
514 if ( $a['text_color'] ) {
515 $colors['text_color'] = $a['text_color'];
516 }
517 if ( $a['primary_color'] ) {
518 $colors['primary_color'] = $a['primary_color'];
519 }
520
521 if ( ! empty( $colors ) ) {
522 foreach ( $colors as &$color ) {
523 $color = str_replace( '#', '', $color ); // Strip out any # characters.
524 }
525
526 $a['url'] = add_query_arg( $colors, $a['url'] );
527 }
528
529 $hide_fields = array(
530 'hide_gdpr_banner' => $a['hide_gdpr_banner'],
531 'hide_landing_page_details' => $a['hide_landing_page_details'],
532 'hide_event_type_details' => $a['hide_event_type_details'],
533 );
534 $a['url'] = add_query_arg( $hide_fields, $a['url'] );
535
536 // Sanitize the classes (remove dots and normalize the number of spaces between each one).
537 $classes = preg_replace( '/[ ]*\./', ' ', $a['classes'] );
538
539 ob_start();
540 ?>
541 <!-- UseStrict's Calendly Embedder - Calendly inline widget start -->
542 <div id="wpcalel-calendly-inline-<?php echo esc_attr( $count ); ?>"
543 class="calendly-inline-widget <?php echo esc_attr( $classes ); ?>"
544 style="min-width:<?php echo esc_attr( $a['min-width'] ); ?>; height:<?php echo esc_attr( $a['height'] ); ?>; <?php echo esc_attr( $a['styles'] ); ?>"
545 data-auto-load="false"
546 data-wpcalel-type="inline"
547 data-wpcalel-url="<?php echo esc_url( $a['url'] ); ?>"
548 data-wpcalel-prefill="<?php echo $a['prefill'] ? 'true' : 'false'; ?>"
549 data-wpcalel-query-str="<?php echo $a['query_str'] ? 'true' : 'false'; ?>"
550 <?php foreach ( range( 1, 10 ) as $key ) : ?>
551 <?php if ( ! empty( $a[ 'a' . $key ] ) ) : ?>
552 data-wpcalel-<?php echo esc_attr( 'a' . $key ); ?>="<?php echo esc_attr( $a[ 'a' . $key ] ); ?>"
553 <?php endif; ?>
554 <?php endforeach; ?>
555 >
556 <div class="calendly-spinner">
557 <div class="calendly-bounce1"></div><div class="calendly-bounce2"></div><div class="calendly-bounce3"></div>
558 </div>
559 </div>
560 <!-- UseStrict's Calendly Embedder - Calendly inline widget end -->
561 <?php
562
563 $content = ob_get_clean();
564
565 return $content;
566 }
567
568 /**
569 * Ajax handler for user-info prefill.
570 */
571 public function ajax_get_user_info() {
572 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : null;
573
574 if ( ! isset( $nonce ) || ! wp_verify_nonce( $nonce, 'wpcalel-calendly' ) ) {
575 wp_send_json_error( __( 'Missing or bad nonce', 'cal-embedder-lite' ), 500 );
576 }
577
578 $data = array();
579 if ( is_user_logged_in() ) {
580 $user = wp_get_current_user();
581 $data['name'] = $user->display_name;
582 $data['firstName'] = $user->first_name;
583 $data['lastName'] = $user->last_name;
584 $data['email'] = $user->user_email;
585 }
586
587 wp_send_json_success( $data, 200 );
588 }
589
590
591 /**
592 * Adds the settings menu item.
593 */
594 public function add_options_page() {
595 $settings_page = add_options_page(
596 'UseStrict\'s Calendly Embedder',
597 'UseStrict\'s Calendly Embedder',
598 'manage_options',
599 __CLASS__,
600 array( $this, 'show_admin' )
601 );
602
603 $this->settings_page = $settings_page;
604
605 // Add CSS and JS.
606 add_action( 'admin_head-' . $settings_page, array( $this, 'add_admin_scripts' ) );
607
608 add_filter( 'plugin_action_links', array( $this, 'add_plugin_link' ), 10, 2 );
609 }
610
611 /**
612 * Adds the admin JS and CSS files
613 */
614 public function add_admin_scripts() {
615 wp_enqueue_style( 'wp-color-picker' );
616 wp_enqueue_script( 'wp-color-picker' );
617
618 wp_enqueue_style( 'wpcalel-settings-admin', $this->environment->css_url . '/admin-settings.css', array( 'wp-color-picker' ), self::VERSION );
619 wp_enqueue_script( 'wpcalel-settings-admin', $this->environment->js_url . '/admin-settings.js', array( 'jquery', 'wp-color-picker' ), self::VERSION, $in_footer = true );
620
621 $min = defined( 'WP_DEBUG' ) && WP_DEBUG ? '.min' : '';
622 wp_enqueue_script( 'wpcalel-jquery-template', $this->environment->js_url . "/jquery-tmpl{$min}.js", array( 'jquery' ), self::VERSION, $in_footer = true );
623 }
624
625 /**
626 * Shows the settings screen.
627 */
628 public function show_admin() {
629 $wpcalel_url_info = get_transient( self::$transient );
630
631 if ( empty( $wpcalel_url_info ) ) {
632 $wpcalel_url_info = isset( $this->settings->api_key ) || isset( $this->settings->pat ) ? $this->get_calendly_data() : array();
633 }
634
635 include __DIR__ . '/admin-settings.tmpl.php';
636 }
637
638 /**
639 * Whitelists our settings
640 */
641 public function register_setting() {
642 register_setting( $this->settings_name, $this->settings_name, array( $this, 'validate_settings' ) );
643 }
644
645
646 /**
647 * Fetches Calendly information, routing the request to the correct API version.
648 */
649 private function get_calendly_data() {
650 return isset( $this->settings->api_key ) ? $this->get_calendly_data_v1() : $this->get_calendly_data_v2();
651 }
652
653
654 /**
655 * Fetches Calendly information via the API version 2.
656 */
657 private function get_calendly_data_v2() {
658 $pat = $this->settings->pat;
659 $args = $this->build_args_for_pat( $pat );
660 $data = array();
661
662 // Get the user.
663 $user = $this->get_calendly_user( $args );
664
665 if ( ! $user ) {
666 add_settings_error( __CLASS__, esc_attr( 'Personal Access Token' ), __( 'The Personal Access Token used is incorrect or has been revoked.', 'cal-embedder-lite' ), 'error' );
667 return;
668 }
669
670 // Get the Event Types.
671 $response = wp_remote_get( $this->calendly_api_url_v2 . '/event_types?user=' . $user->uri, $args );
672
673 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
674 $body = json_decode( wp_remote_retrieve_body( $response ) );
675
676 /* translators: 1: the Calendly account holder's name */
677 $owner = sprintf( __( 'Profile (%1$s)', 'cal-embedder-lite' ), $user->name );
678 $owner_url = $user->scheduling_url;
679
680 $data[ $owner_url ] = $owner;
681
682 foreach ( $body->collection as $event_type ) {
683 if ( $event_type->scheduling_url === $owner_url ) {
684 continue;
685 }
686
687 $name = $event_type->name;
688 $url = $event_type->scheduling_url;
689
690 $data[ $url ] = $name;
691 }
692
693 /**
694 * Store the transient for 2 days. We automatically refresh after that.
695 */
696 set_transient( self::$transient, $data, DAY_IN_SECONDS * 2 );
697 }
698
699 return $data;
700 }
701
702
703 /**
704 * Fetches the Calendly user given the PAT
705 *
706 * @param array $args The header arguments.
707 * @return object|boolean
708 */
709 public function get_calendly_user( $args ) {
710 $response = wp_remote_get( $this->calendly_api_url_v2 . '/users/me', $args );
711
712 $user = false;
713 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
714 $body = json_decode( wp_remote_retrieve_body( $response ) );
715
716 $user = (object) array(
717 'uri' => $body->resource->uri,
718 'name' => $body->resource->name,
719 'scheduling_url' => $body->resource->scheduling_url,
720 );
721 }
722
723 return $user;
724 }
725
726
727 /**
728 * Fetches Calendly information via the API version 1.
729 */
730 private function get_calendly_data_v1() {
731 $api_key = $this->settings->api_key;
732
733 $args = array(
734 'headers' => array(
735 'X-TOKEN' => $this->settings->api_key,
736 ),
737 );
738
739 $data = array();
740
741 // Get the Event Types.
742 $response = wp_remote_get( $this->calendly_api_url_v1 . '/users/me/event_types?include=owner', $args );
743
744 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
745 $body = json_decode( wp_remote_retrieve_body( $response ) );
746
747 /* translators: 1: the Calendly account holder's name */
748 $owner = sprintf( __( 'Profile (%1$s)', 'cal-embedder-lite' ), $body->included[0]->attributes->name );
749 $owner_url = $body->included[0]->attributes->url;
750
751 $data[ $owner_url ] = $owner;
752
753 foreach ( $body->data as $event_type ) {
754 if ( $event_type->attributes->url === $owner_url ) {
755 continue;
756 }
757
758 $name = $event_type->attributes->name;
759 $url = $event_type->attributes->url;
760
761 $data[ $url ] = $name;
762 }
763
764 /**
765 * Store the transient for 2 days. We automatically refresh after that.
766 */
767 set_transient( self::$transient, $data, DAY_IN_SECONDS * 2 );
768 }
769
770 return $data;
771 }
772
773
774 /**
775 * Ensure some basic settings
776 *
777 * @param array $_post POSTed values.
778 * @return string
779 */
780 public static function validate_settings( $_post ) {
781 ksort( $_post );
782 $user = false;
783 foreach ( $_post as $key => $value ) {
784 switch ( $key ) {
785 case 'api_key':
786 if ( $value && empty( $_post['disconnect'] ) ) {
787 add_settings_error( __CLASS__, esc_attr( 'API Key' ), __( 'The API Key is deprecated. Use a Personal Access Token instead.', 'cal-embedder-lite' ) );
788 unset( $_post[ $key ] );
789 }
790 break;
791 case 'pat':
792 $value = trim( $value );
793 if ( ! $value && empty( $_post['disconnect'] ) ) {
794 add_settings_error( __CLASS__, esc_attr( 'Personal Access Token' ), __( 'The Personal Access Token is required', 'cal-embedder-lite' ) );
795 unset( $_post[ $key ] );
796 } else {
797 $args = wpcalel()->build_args_for_pat( $value );
798 $user = wpcalel()->get_calendly_user( $args );
799 if ( ! $user ) {
800 add_settings_error( __CLASS__, esc_attr( 'Personal Access Token' ), __( 'The Personal Access Token used is incorrect or has been revoked.', 'cal-embedder-lite' ) );
801 unset( $_post[ $key ] );
802 }
803 }
804 break;
805 case 'disconnect':
806 unset( $_post['api_key'] );
807 unset( $_post['pat'] );
808 delete_transient( self::$transient );
809 add_settings_error( __CLASS__, esc_attr( 'API Key' ), __( 'Disconnected!', 'cal-embedder-lite' ), 'success' );
810 break;
811 case 'refresh':
812 delete_transient( self::$transient );
813 if ( $user ) {
814 add_settings_error( __CLASS__, esc_attr( 'Refresh URLs' ), __( 'Refreshed!', 'cal-embedder-lite' ), 'success' );
815 }
816 break;
817 default:
818 }
819 }
820
821 return $_post;
822 }
823
824 /**
825 * Builds the args array for calling Calendly's API.
826 *
827 * @param string $pat The Personal Access Token.
828 * @return string[][]
829 */
830 public function build_args_for_pat( $pat ) {
831 $args = array(
832 'headers' => array(
833 'Authorization' => 'Bearer ' . $pat,
834 'Content-type: application/json',
835 ),
836 );
837
838 return $args;
839 }
840
841 /**
842 * Add 'Settings' to the plugin actions.
843 *
844 * @param array $plugin_actions Array of plugin actions.
845 * @param string $plugin_file The name of the plugin file.
846 * @return array
847 */
848 public function add_plugin_link( $plugin_actions, $plugin_file ) {
849 if ( $this->environment->plugin_basename === $plugin_file ) {
850 /* translators: the URL of the settings page */
851 $plugin_actions['PluginClass_settings'] = sprintf( __( '<a href="%s">Settings</a>', 'cal-embedder-lite' ), esc_url( admin_url( 'options-general.php?page=' . __CLASS__ ) ) );
852 }
853
854 return $plugin_actions;
855 }
856 } // End of class.
857
858
859 /**
860 * Wrapper function for our instance.
861 *
862 * @return Wp_Cal_Embed_Lite
863 */
864 function wpcalel() {
865 return Wp_Cal_Embed_Lite::instance();
866 }
867
868 wpcalel(); // Kick off the class.
869
870 endif; // End if class_exists.
871
872 /**
873 * End file cal-embedder-lite.php
874 */
875