1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Calendly Block. |
4
|
|
|
* |
5
|
|
|
* @since 8.2.0 |
6
|
|
|
* |
7
|
|
|
* @package Jetpack |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Jetpack\Calendly_Block; |
11
|
|
|
|
12
|
|
|
const FEATURE_NAME = 'calendly'; |
13
|
|
|
const BLOCK_NAME = 'jetpack/' . FEATURE_NAME; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Check if the block should be available on the site. |
17
|
|
|
* |
18
|
|
|
* @return bool |
19
|
|
|
*/ |
20
|
|
View Code Duplication |
function is_available() { |
|
|
|
|
21
|
|
|
if ( |
22
|
|
|
defined( 'IS_WPCOM' ) |
23
|
|
|
&& IS_WPCOM |
24
|
|
|
&& function_exists( 'has_any_blog_stickers' ) |
25
|
|
|
) { |
26
|
|
|
if ( has_any_blog_stickers( |
27
|
|
|
array( 'premium-plan', 'business-plan', 'ecommerce-plan' ), |
28
|
|
|
get_current_blog_id() |
29
|
|
|
) ) { |
30
|
|
|
return true; |
31
|
|
|
} |
32
|
|
|
return false; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
return true; |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Registers the block for use in Gutenberg |
40
|
|
|
* This is done via an action so that we can disable |
41
|
|
|
* registration if we need to. |
42
|
|
|
*/ |
43
|
|
|
function register_block() { |
44
|
|
|
if ( is_available() ) { |
45
|
|
|
jetpack_register_block( |
46
|
|
|
BLOCK_NAME, |
47
|
|
|
array( 'render_callback' => 'Jetpack\Calendly_Block\load_assets' ) |
48
|
|
|
); |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
add_action( 'init', 'Jetpack\Calendly_Block\register_block' ); |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Set the availability of the block as the editor |
55
|
|
|
* is loaded |
56
|
|
|
*/ |
57
|
|
View Code Duplication |
function set_availability() { |
|
|
|
|
58
|
|
|
if ( is_available() ) { |
59
|
|
|
\Jetpack_Gutenberg::set_extension_available( BLOCK_NAME ); |
60
|
|
|
} else { |
61
|
|
|
\Jetpack_Gutenberg::set_extension_unavailable( |
62
|
|
|
BLOCK_NAME, |
63
|
|
|
'missing_plan', |
64
|
|
|
array( |
65
|
|
|
'required_feature' => 'calendly', |
66
|
|
|
'required_plan' => 'value_bundle', |
67
|
|
|
) |
68
|
|
|
); |
69
|
|
|
} |
70
|
|
|
} |
71
|
|
|
add_action( 'init', 'Jetpack\Calendly_Block\set_availability' ); |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Enqueues the Calendly JS library, and adds an inline |
75
|
|
|
* function to attach event handlers to the button |
76
|
|
|
*/ |
77
|
|
|
function enqueue_calendly_js() { |
78
|
|
|
wp_enqueue_script( |
79
|
|
|
'jetpack-calendly-external-js', |
80
|
|
|
'https://assets.calendly.com/assets/external/widget.js', |
81
|
|
|
null, |
82
|
|
|
JETPACK__VERSION, |
83
|
|
|
false |
84
|
|
|
); |
85
|
|
|
wp_add_inline_script( |
86
|
|
|
'jetpack-calendly-external-js', |
87
|
|
|
"function calendly_attach_link_events( elementId ) { |
88
|
|
|
var widget = document.getElementById( elementId ); |
89
|
|
|
if ( widget ) { |
90
|
|
|
widget.addEventListener( 'click', function( event ) { |
91
|
|
|
event.preventDefault(); |
92
|
|
|
Calendly.initPopupWidget({url:event.target.href}); |
93
|
|
|
} ); |
94
|
|
|
|
95
|
|
|
widget.addEventListener( 'keydown', function( event ) { |
96
|
|
|
// Enter and space keys. |
97
|
|
|
if ( event.keyCode === 13 || event.keyCode === 32 ) { |
98
|
|
|
event.preventDefault(); |
99
|
|
|
event.target && event.target.click(); |
100
|
|
|
} |
101
|
|
|
} ); |
102
|
|
|
} |
103
|
|
|
}" |
104
|
|
|
); |
105
|
|
|
} |
106
|
|
|
/** |
107
|
|
|
* Calendly block registration/dependency declaration. |
108
|
|
|
* |
109
|
|
|
* @param array $attr Array containing the Calendly block attributes. |
110
|
|
|
* @param string $content String containing the Calendly block content. |
111
|
|
|
* |
112
|
|
|
* @return string |
113
|
|
|
*/ |
114
|
|
|
function load_assets( $attr, $content ) { |
115
|
|
|
if ( is_admin() ) { |
116
|
|
|
return; |
117
|
|
|
} |
118
|
|
|
$url = \Jetpack_Gutenberg::validate_block_embed_url( |
119
|
|
|
get_attribute( $attr, 'url' ), |
120
|
|
|
array( 'calendly.com' ) |
121
|
|
|
); |
122
|
|
|
if ( empty( $url ) ) { |
123
|
|
|
return; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$style = get_attribute( $attr, 'style' ); |
127
|
|
|
$hide_event_type_details = get_attribute( $attr, 'hideEventTypeDetails' ); |
128
|
|
|
$background_color = get_attribute( $attr, 'backgroundColor' ); |
129
|
|
|
$text_color = get_attribute( $attr, 'textColor' ); |
130
|
|
|
$primary_color = get_attribute( $attr, 'primaryColor' ); |
131
|
|
|
$classes = \Jetpack_Gutenberg::block_classes( 'calendly', $attr ); |
132
|
|
|
$is_amp_request = class_exists( 'Jetpack_AMP_Support' ) && \Jetpack_AMP_Support::is_amp_request(); |
133
|
|
|
$block_id = wp_unique_id( 'calendly-block-' ); |
134
|
|
|
|
135
|
|
|
/* |
136
|
|
|
* Enqueue necessary scripts and styles. |
137
|
|
|
*/ |
138
|
|
|
\Jetpack_Gutenberg::load_assets_as_required( 'calendly' ); |
139
|
|
|
if ( ! wp_script_is( 'jetpack-calendly-external-js' ) && ! $is_amp_request ) { |
140
|
|
|
enqueue_calendly_js(); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$orig_url = $url; |
144
|
|
|
$url = add_query_arg( |
145
|
|
|
array( |
146
|
|
|
'hide_event_type_details' => (int) $hide_event_type_details, |
147
|
|
|
'background_color' => sanitize_hex_color_no_hash( $background_color ), |
148
|
|
|
'text_color' => sanitize_hex_color_no_hash( $text_color ), |
149
|
|
|
'primary_color' => sanitize_hex_color_no_hash( $primary_color ), |
150
|
|
|
), |
151
|
|
|
$url |
152
|
|
|
); |
153
|
|
|
|
154
|
|
|
if ( 'link' === $style ) { |
155
|
|
|
if ( ! wp_style_is( 'jetpack-calendly-external-css' ) ) { |
156
|
|
|
wp_enqueue_style( 'jetpack-calendly-external-css', 'https://assets.calendly.com/assets/external/widget.css', null, JETPACK__VERSION ); |
157
|
|
|
} |
158
|
|
|
if ( strstr( $content, sprintf( '>%s</a>', $orig_url ) ) ) { |
159
|
|
|
$content = deprecated_render_button( $attr, $block_id, $classes, $url ); |
160
|
|
|
} else { |
161
|
|
|
// It's the new version so simply substitute the ID. |
162
|
|
|
$content = preg_replace( '/data-id-attr="placeholder"/', 'id="' . esc_attr( $block_id ) . '"', $content ); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
if ( ! $is_amp_request ) { |
166
|
|
|
wp_add_inline_script( 'jetpack-calendly-external-js', sprintf( "calendly_attach_link_events( '%s' )", esc_js( $block_id ) ) ); |
167
|
|
|
} |
168
|
|
|
} else { // Inline style. |
169
|
|
|
$content = sprintf( |
170
|
|
|
'<div class="%1$s" id="%2$s"></div>', |
171
|
|
|
esc_attr( $classes ), |
172
|
|
|
esc_attr( $block_id ) |
173
|
|
|
); |
174
|
|
|
$script = <<<JS_END |
175
|
|
|
Calendly.initInlineWidget({ |
176
|
|
|
url: '%s', |
177
|
|
|
parentElement: document.getElementById('%s'), |
178
|
|
|
inlineStyles: false, |
179
|
|
|
}); |
180
|
|
|
JS_END; |
181
|
|
|
wp_add_inline_script( 'jetpack-calendly-external-js', sprintf( $script, esc_url( $url ), esc_js( $block_id ) ) ); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
return $content; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* The renders the legacy version of the button HTML. |
189
|
|
|
* |
190
|
|
|
* @param array $attr Array containing the Calendly block attributes. |
191
|
|
|
* @param string $block_id The value for the ID attribute of the link. |
192
|
|
|
* @param string $classes The CSS classes for the wrapper div. |
193
|
|
|
* @param string $url Calendly URL for the link HREF. |
194
|
|
|
*/ |
195
|
|
|
function deprecated_render_button( $attr, $block_id, $classes, $url ) { |
196
|
|
|
// This is the lecacy version, so create the full link content. |
197
|
|
|
$submit_button_text = get_attribute( $attr, 'submitButtonText' ); |
198
|
|
|
$submit_button_classes = get_attribute( $attr, 'submitButtonClasses' ); |
199
|
|
|
$submit_button_text_color = get_attribute( $attr, 'customTextButtonColor' ); |
200
|
|
|
$submit_button_background_color = get_attribute( $attr, 'customBackgroundButtonColor' ); |
201
|
|
|
|
202
|
|
|
/* |
203
|
|
|
* If we have some additional styles from the editor |
204
|
|
|
* (a custom text color, custom bg color, or both ) |
205
|
|
|
* Let's add that CSS inline. |
206
|
|
|
*/ |
207
|
|
|
if ( ! empty( $submit_button_text_color ) || ! empty( $submit_button_background_color ) ) { |
208
|
|
|
$inline_styles = sprintf( |
209
|
|
|
'#%1$s .wp-block-button__link{%2$s%3$s}', |
210
|
|
|
esc_attr( $block_id ), |
211
|
|
|
! empty( $submit_button_text_color ) |
212
|
|
|
? 'color:#' . sanitize_hex_color_no_hash( $submit_button_text_color ) . ';' |
213
|
|
|
: '', |
214
|
|
|
! empty( $submit_button_background_color ) |
215
|
|
|
? 'background-color:#' . sanitize_hex_color_no_hash( $submit_button_background_color ) . ';' |
216
|
|
|
: '' |
217
|
|
|
); |
218
|
|
|
wp_add_inline_style( 'jetpack-calendly-external-css', $inline_styles ); |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
return sprintf( |
222
|
|
|
'<div class="%1$s" id="%2$s"><a class="%3$s" href="%4$s" role="button">%5$s</a></div>', |
223
|
|
|
esc_attr( $classes ), |
224
|
|
|
esc_attr( $block_id ), |
225
|
|
|
! empty( $submit_button_classes ) ? esc_attr( $submit_button_classes ) : 'wp-block-button__link', |
226
|
|
|
esc_js( $url ), |
227
|
|
|
wp_kses_post( $submit_button_text ) |
228
|
|
|
); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Get filtered attributes. |
234
|
|
|
* |
235
|
|
|
* @param array $attributes Array containing the Calendly block attributes. |
236
|
|
|
* @param string $attribute_name String containing the attribute name to get. |
237
|
|
|
* |
238
|
|
|
* @return string |
239
|
|
|
*/ |
240
|
|
|
function get_attribute( $attributes, $attribute_name ) { |
241
|
|
|
if ( isset( $attributes[ $attribute_name ] ) ) { |
242
|
|
|
return $attributes[ $attribute_name ]; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
$default_attributes = array( |
246
|
|
|
'style' => 'inline', |
247
|
|
|
'submitButtonText' => esc_html__( 'Schedule time with me', 'jetpack' ), |
248
|
|
|
'backgroundColor' => 'ffffff', |
249
|
|
|
'textColor' => '4D5055', |
250
|
|
|
'primaryColor' => '00A2FF', |
251
|
|
|
'hideEventTypeDetails' => false, |
252
|
|
|
); |
253
|
|
|
|
254
|
|
|
if ( isset( $default_attributes[ $attribute_name ] ) ) { |
255
|
|
|
return $default_attributes[ $attribute_name ]; |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.