PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.2.2
Jetpack – WP Security, Backup, Speed, & Growth v7.2.2
16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 All 502 releases
jetpack / modules / shortcodes / crowdsignal.php

crowdsignal.php in Jetpack – WP Security, Backup, Speed, & Growth 7.2.2, at modules/shortcodes/crowdsignal.php

611 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // Keep compatibility with polldaddy-plugin
4 if ( ! class_exists( 'CrowdsignalShortcode' ) && ! class_exists( 'PolldaddyShortcode' ) ) {
5
6 /**
7 * Class wrapper for Crowdsignal shortcodes
8 */
9
10 class CrowdsignalShortcode {
11
12 static $add_script = false;
13 static $scripts = false;
14
15 /**
16 * Add all the actions & resgister the shortcode
17 */
18 function __construct() {
19 if ( defined( 'GLOBAL_TAGS' ) == false ) {
20 add_shortcode( 'crowdsignal', array( $this, 'crowdsignal_shortcode' ) );
21 add_shortcode( 'polldaddy', array( $this, 'crowdsignal_shortcode' ) );
22
23 add_filter( 'pre_kses', array( $this, 'crowdsignal_embed_to_shortcode' ) );
24 }
25 add_action( 'wp_enqueue_scripts', array( $this, 'check_infinite' ) );
26 add_action( 'infinite_scroll_render', array( $this, 'crowdsignal_shortcode_infinite' ), 11 );
27 }
28
29 private function get_async_code( array $settings, $survey_link ) {
30 $include = <<<CONTAINER
31 ( function( d, c, j ) {
32 if ( !d.getElementById( j ) ) {
33 var pd = d.createElement( c ), s;
34 pd.id = j;
35 pd.src = 'https://polldaddy.com/survey.js';
36 s = d.getElementsByTagName( c )[0];
37 s.parentNode.insertBefore( pd, s );
38 }
39 }( document, 'script', 'pd-embed' ) );
40 CONTAINER;
41
42 // Compress it a bit
43 $include = $this->compress_it( $include );
44
45 $placeholder =
46 '<div class="cs-embed pd-embed" data-settings="'
47 . esc_attr( json_encode( $settings ) )
48 . '"></div>';
49 if ( 'button' === $settings['type'] ) {
50 $placeholder =
51 '<a class="cs-embed pd-embed" href="'
52 . esc_attr( $survey_link )
53 . '" data-settings="'
54 . esc_attr( json_encode( $settings ) )
55 . '">'
56 . esc_html( $settings['title'] )
57 . '</a>';
58 }
59
60 $js_include = $placeholder . "\n";
61 $js_include .= '<script type="text/javascript"><!--//--><![CDATA[//><!--' . "\n";
62 $js_include .= $include . "\n";
63 $js_include .= "//--><!]]></script>\n";
64
65 if ( 'button' !== $settings['type'] ) {
66 $js_include .= '<noscript>' . $survey_link . "</noscript>\n";
67 }
68
69 return $js_include;
70 }
71
72 private function compress_it( $js ) {
73 $js = str_replace( array( "\n", "\t", "\r" ), '', $js );
74 $js = preg_replace( '/\s*([,:\?\{;\-=\(\)])\s*/', '$1', $js );
75 return $js;
76 }
77
78 /*
79 * Crowdsignal Poll Embed script - transforms code that looks like that:
80 * <script type="text/javascript" charset="utf-8" async src="http://static.polldaddy.com/p/123456.js"></script>
81 * <noscript><a href="http://polldaddy.com/poll/123456/">What is your favourite color?</a></noscript>
82 * into the [crowdsignal poll=...] shortcode format
83 */
84 function crowdsignal_embed_to_shortcode( $content ) {
85
86 if ( ! is_string( $content ) || false === strpos( $content, 'polldaddy.com/p/' ) ) {
87 return $content;
88 }
89
90 $regexes = array();
91
92 $regexes[] = '#<script[^>]+?src="https?://(secure|static)\.polldaddy\.com/p/([0-9]+)\.js"[^>]*+>\s*?</script>\r?\n?(<noscript>.*?</noscript>)?#i';
93
94 $regexes[] = '#&lt;script(?:[^&]|&(?!gt;))+?src="https?://(secure|static)\.polldaddy\.com/p/([0-9]+)\.js"(?:[^&]|&(?!gt;))*+&gt;\s*?&lt;/script&gt;\r?\n?(&lt;noscript&gt;.*?&lt;/noscript&gt;)?#i';
95
96 foreach ( $regexes as $regex ) {
97 if ( ! preg_match_all( $regex, $content, $matches, PREG_SET_ORDER ) ) {
98 continue;
99 }
100
101 foreach ( $matches as $match ) {
102 if ( ! isset( $match[2] ) ) {
103 continue;
104 }
105
106 $id = (int) $match[2];
107
108 if ( $id > 0 ) {
109 $content = str_replace( $match[0], " [crowdsignal poll=$id]", $content );
110 /** This action is documented in modules/shortcodes/youtube.php */
111 do_action( 'jetpack_embed_to_shortcode', 'crowdsignal', $id );
112 }
113 }
114 }
115
116 return $content;
117 }
118
119 /**
120 * Shortcode for polldadddy
121 * [crowdsignal poll|survey|rating="123456"]
122 */
123 function crowdsignal_shortcode( $atts ) {
124 global $post;
125 global $content_width;
126
127 /**
128 * Variables extracted from $atts.
129 *
130 * @var string $survey
131 * @var string $link_text
132 * @var string $poll
133 * @var string $rating
134 * @var string $unique_id
135 * @var string $item_id
136 * @var string $title
137 * @var string $permalink
138 * @var int $cb
139 * @var string $type
140 * @var string $body
141 * @var string $button
142 * @var string $text_color
143 * @var string $back_color
144 * @var string $align
145 * @var string $style
146 * @var int $width
147 * @var int $height
148 * @var int $delay
149 * @var string $visit
150 * @var string $domain
151 * @var string $id
152 */
153 extract( shortcode_atts( array(
154 'survey' => null,
155 'link_text' => 'Take Our Survey',
156 'poll' => 'empty',
157 'rating' => 'empty',
158 'unique_id' => null,
159 'item_id' => null,
160 'title' => null,
161 'permalink' => null,
162 'cb' => 0,
163 'type' => 'button',
164 'body' => '',
165 'button' => '',
166 'text_color' => '000000',
167 'back_color' => 'FFFFFF',
168 'align' => '',
169 'style' => '',
170 'width' => $content_width,
171 'height' => floor( $content_width * 3 / 4 ),
172 'delay' => 100,
173 'visit' => 'single',
174 'domain' => '',
175 'id' => '',
176 ), $atts, 'crowdsignal' ) );
177
178 if ( ! is_array( $atts ) ) {
179 return '<!-- Crowdsignal shortcode passed invalid attributes -->';
180 }
181
182 $inline = ! in_the_loop();
183 $no_script = false;
184 $infinite_scroll = false;
185
186 if ( is_home() && current_theme_supports( 'infinite-scroll' ) ) {
187 $infinite_scroll = true;
188 }
189
190 if ( defined( 'PADPRESS_LOADED' ) ) {
191 $inline = true;
192 }
193
194 if ( function_exists( 'get_option' ) && get_option( 'polldaddy_load_poll_inline' ) ) {
195 $inline = true;
196 }
197
198 if ( is_feed() || ( defined( 'DOING_AJAX' ) && ! $infinite_scroll ) ) {
199 $no_script = false;
200 }
201
202 self::$add_script = $infinite_scroll;
203
204 if ( intval( $rating ) > 0 && ! $no_script ) { //rating embed
205
206 if ( empty( $unique_id ) ) {
207 $unique_id = is_page() ? 'wp-page-' . $post->ID : 'wp-post-' . $post->ID;
208 }
209
210 if ( empty( $item_id ) ) {
211 $item_id = is_page() ? '_page_' . $post->ID : '_post_' . $post->ID;
212 }
213
214 if ( empty( $title ) ) {
215 /** This filter is documented in core/src/wp-includes/general-template.php */
216 $title = apply_filters( 'wp_title', $post->post_title, '', '' );
217 }
218
219 if ( empty( $permalink ) ) {
220 $permalink = get_permalink( $post->ID );
221 }
222
223 $rating = intval( $rating );
224 $unique_id = preg_replace( '/[^\-_a-z0-9]/i', '', wp_strip_all_tags( $unique_id ) );
225 $item_id = wp_strip_all_tags( $item_id );
226 $item_id = preg_replace( '/[^_a-z0-9]/i', '', $item_id );
227
228 $settings = json_encode( array(
229 'id' => $rating,
230 'unique_id' => $unique_id,
231 'title' => rawurlencode( trim( $title ) ),
232 'permalink' => esc_url( $permalink ),
233 'item_id' => $item_id,
234 ) );
235
236 $item_id = esc_js( $item_id );
237
238 if ( Jetpack_AMP_Support::is_amp_request() ) {
239 return sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $permalink ), esc_html( trim( $title ) ) );
240 } elseif ( $inline ) {
241 return <<<SCRIPT
242 <div class="cs-rating pd-rating" id="pd_rating_holder_{$rating}{$item_id}"></div>
243 <script type="text/javascript" charset="UTF-8"><!--//--><![CDATA[//><!--
244 PDRTJS_settings_{$rating}{$item_id}={$settings};
245 //--><!]]></script>
246 <script type="text/javascript" charset="UTF-8" async src="https://polldaddy.com/js/rating/rating.js"></script>
247 SCRIPT;
248 } else {
249 if ( false === self::$scripts ) {
250 self::$scripts = array();
251 }
252
253 $data = array( 'id' => $rating, 'item_id' => $item_id, 'settings' => $settings );
254
255 self::$scripts['rating'][] = $data;
256
257 add_action( 'wp_footer', array( $this, 'generate_scripts' ) );
258
259 $data = esc_attr( json_encode( $data ) );
260
261 if ( $infinite_scroll ) {
262 return <<<CONTAINER
263 <div class="cs-rating pd-rating" id="pd_rating_holder_{$rating}{$item_id}" data-settings="{$data}"></div>
264 CONTAINER;
265 } else {
266 return <<<CONTAINER
267 <div class="cs-rating pd-rating" id="pd_rating_holder_{$rating}{$item_id}"></div>
268 CONTAINER;
269 }
270 }
271 } elseif ( intval( $poll ) > 0 ) { //poll embed
272
273 if ( empty( $title ) ) {
274 $title = __( 'Take Our Poll', 'jetpack' );
275 }
276
277 $poll = intval( $poll );
278 $poll_url = sprintf( 'https://poll.fm/%d', $poll );
279 $poll_js = sprintf( 'https://secure.polldaddy.com/p/%d.js', $poll );
280 $poll_link = sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $poll_url ), esc_html( $title ) );
281
282 if ( $no_script || Jetpack_AMP_Support::is_amp_request() ) {
283 return $poll_link;
284 } else {
285 if ( $type == 'slider' && !$inline ) {
286
287 if ( ! in_array( $visit, array( 'single', 'multiple' ) ) ) {
288 $visit = 'single';
289 }
290
291 $settings = array(
292 'type' => 'slider',
293 'embed' => 'poll',
294 'delay' => intval( $delay ),
295 'visit' => $visit,
296 'id' => intval( $poll )
297 );
298
299 return $this->get_async_code( $settings, $poll_link );
300 } else {
301 $cb = ( $cb == 1 ? '?cb='.mktime() : false );
302 $margins = '';
303 $float = '';
304
305 if ( in_array( $align, array( 'right', 'left' ) ) ) {
306 $float = sprintf( 'float: %s;', $align );
307
308 if ( $align == 'left')
309 $margins = 'margin: 0px 10px 0px 0px;';
310 elseif ( $align == 'right' )
311 $margins = 'margin: 0px 0px 0px 10px';
312 }
313
314 // Force the normal style embed on single posts/pages otherwise it's not rendered on infinite scroll themed blogs ('infinite_scroll_render' isn't fired)
315 if ( is_singular() ) {
316 $inline = true;
317 }
318
319 if ( false === $cb && ! $inline ) {
320 if ( false === self::$scripts ) {
321 self::$scripts = array();
322 }
323
324 $data = array( 'url' => $poll_js );
325
326 self::$scripts['poll'][intval( $poll )] = $data;
327
328 add_action( 'wp_footer', array( $this, 'generate_scripts' ) );
329
330 $data = esc_attr( json_encode( $data ) );
331
332 $script_url = esc_url_raw( plugins_url( 'js/polldaddy-shortcode.js', __FILE__ ) );
333 $str = <<<CONTAINER
334 <a name="pd_a_{$poll}"></a>
335 <div class="CSS_Poll PDS_Poll" id="PDI_container{$poll}" data-settings="{$data}" style="display:inline-block;{$float}{$margins}"></div>
336 <div id="PD_superContainer"></div>
337 <noscript>{$poll_link}</noscript>
338 CONTAINER;
339
340 $loader = <<<SCRIPT
341 ( function( d, c, j ) {
342 if ( ! d.getElementById( j ) ) {
343 var pd = d.createElement( c ), s;
344 pd.id = j;
345 pd.src = '{$script_url}';
346 s = d.getElementsByTagName( c )[0];
347 s.parentNode.insertBefore( pd, s );
348 } else if ( typeof jQuery !== 'undefined' ) {
349 jQuery( d.body ).trigger( 'pd-script-load' );
350 }
351 } ( document, 'script', 'pd-polldaddy-loader' ) );
352 SCRIPT;
353
354 $loader = $this->compress_it( $loader );
355 $loader = "<script type='text/javascript'>\n" . $loader . "\n</script>";
356
357 return $str . $loader;
358 } else {
359 if ( $inline ) {
360 $cb = '';
361 }
362
363 return <<<CONTAINER
364 <a id="pd_a_{$poll}"></a>
365 <div class="CSS_Poll PDS_Poll" id="PDI_container{$poll}" style="display:inline-block;{$float}{$margins}"></div>
366 <div id="PD_superContainer"></div>
367 <script type="text/javascript" charset="UTF-8" async src="{$poll_js}{$cb}"></script>
368 <noscript>{$poll_link}</noscript>
369 CONTAINER;
370 }
371 }
372 }
373 } elseif ( ! empty( $survey ) ) { //survey embed
374
375 if ( in_array( $type, array( 'iframe', 'button', 'banner', 'slider' ) ) ) {
376
377 if ( empty( $title ) ) {
378 $title = __( 'Take Our Survey', 'jetpack' );
379 if( ! empty( $link_text ) ) {
380 $title = $link_text;
381 }
382 }
383
384 if ( $type == 'banner' || $type == 'slider' )
385 $inline = false;
386
387 $survey = preg_replace( '/[^a-f0-9]/i', '', $survey );
388 $survey_url = esc_url( "https://survey.fm/{$survey}" );
389 $survey_link = sprintf( '<a href="%s" target="_blank">%s</a>', $survey_url, esc_html( $title ) );
390
391 $settings = array();
392
393 // Do we want a full embed code or a link?
394 if ( $no_script || $inline || $infinite_scroll || Jetpack_AMP_Support::is_amp_request() ) {
395 return $survey_link;
396 }
397
398 if ( $type == 'iframe' ) {
399 if ( $height != 'auto' ) {
400 if ( isset( $content_width ) && is_numeric( $width ) && $width > $content_width ) {
401 $width = $content_width;
402 }
403
404 if ( ! $width ) {
405 $width = '100%';
406 } else {
407 $width = (int) $width;
408 }
409
410 if ( ! $height ) {
411 $height = '600';
412 } else {
413 $height = (int) $height;
414 }
415
416 return <<<CONTAINER
417 <iframe src="{$survey_url}?iframe=1" frameborder="0" width="{$width}" height="{$height}" scrolling="auto" allowtransparency="true" marginheight="0" marginwidth="0">{$survey_link}</iframe>
418 CONTAINER;
419 } elseif ( ! empty( $domain ) && ! empty( $id ) ) {
420
421 $domain = preg_replace( '/[^a-z0-9\-]/i', '', $domain );
422 $id = preg_replace( '/[\/\?&\{\}]/', '', $id );
423
424 $auto_src = esc_url( "https://{$domain}.survey.fm/{$id}" );
425 $auto_src = parse_url( $auto_src );
426
427 if ( ! is_array( $auto_src ) || count( $auto_src ) == 0 ) {
428 return '<!-- no crowdsignal output -->';
429 }
430
431 if ( ! isset( $auto_src['host'] ) || ! isset( $auto_src['path'] ) ) {
432 return '<!-- no crowdsignal output -->';
433 }
434
435 $domain = $auto_src['host'] . '/';
436 $id = ltrim( $auto_src['path'], '/' );
437
438 $settings = array(
439 'type' => $type,
440 'auto' => true,
441 'domain' => $domain,
442 'id' => $id
443 );
444 }
445 } else {
446 $text_color = preg_replace( '/[^a-f0-9]/i', '', $text_color );
447 $back_color = preg_replace( '/[^a-f0-9]/i', '', $back_color );
448
449 if (
450 ! in_array(
451 $align,
452 array(
453 'right',
454 'left',
455 'top-left',
456 'top-right',
457 'middle-left',
458 'middle-right',
459 'bottom-left',
460 'bottom-right'
461 )
462 )
463 ) {
464 $align = '';
465 }
466
467 if (
468 ! in_array(
469 $style,
470 array(
471 'inline',
472 'side',
473 'corner',
474 'rounded',
475 'square'
476 )
477 )
478 ) {
479 $style = '';
480 }
481
482 $title = wp_strip_all_tags( $title );
483 $body = wp_strip_all_tags( $body );
484 $button = wp_strip_all_tags( $button );
485
486 $settings = array_filter( array(
487 'title' => $title,
488 'type' => $type,
489 'body' => $body,
490 'button' => $button,
491 'text_color' => $text_color,
492 'back_color' => $back_color,
493 'align' => $align,
494 'style' => $style,
495 'id' => $survey,
496 ) );
497 }
498
499 if ( empty( $settings ) ) {
500 return '<!-- no crowdsignal output -->';
501 }
502
503 return $this->get_async_code( $settings, $survey_link );
504 }
505 } else {
506 return '<!-- no crowdsignal output -->';
507 }
508 }
509
510 function generate_scripts() {
511 $script = '';
512
513 if ( is_array( self::$scripts ) ) {
514 if ( isset( self::$scripts['rating'] ) ) {
515 $script = "<script type='text/javascript' charset='UTF-8' id='polldaddyRatings'><!--//--><![CDATA[//><!--\n";
516 foreach( self::$scripts['rating'] as $rating ) {
517 $script .= "PDRTJS_settings_{$rating['id']}{$rating['item_id']}={$rating['settings']}; if ( typeof PDRTJS_RATING !== 'undefined' ){if ( typeof PDRTJS_{$rating['id']}{$rating['item_id']} == 'undefined' ){PDRTJS_{$rating['id']}{$rating['item_id']} = new PDRTJS_RATING( PDRTJS_settings_{$rating['id']}{$rating['item_id']} );}}";
518 }
519 $script .= "\n//--><!]]></script><script type='text/javascript' charset='UTF-8' async src='https://polldaddy.com/js/rating/rating.js'></script>";
520
521 }
522
523 if ( isset( self::$scripts['poll'] ) ) {
524 foreach( self::$scripts['poll'] as $poll ) {
525 $script .= "<script type='text/javascript' charset='UTF-8' async src='{$poll['url']}'></script>";
526 }
527 }
528 }
529
530 self::$scripts = false;
531 echo $script;
532 }
533
534 /**
535 * If the theme uses infinite scroll, include jquery at the start
536 */
537 function check_infinite() {
538 if (
539 current_theme_supports( 'infinite-scroll' )
540 && class_exists( 'The_Neverending_Home_Page' )
541 && The_Neverending_Home_Page::archive_supports_infinity()
542 ) {
543 wp_enqueue_script( 'jquery' );
544 }
545 }
546
547 /**
548 * Dynamically load the .js, if needed
549 *
550 * This hooks in late (priority 11) to infinite_scroll_render to determine
551 * a posteriori if a shortcode has been called.
552 */
553 function crowdsignal_shortcode_infinite() {
554 // only try to load if a shortcode has been called and theme supports infinite scroll
555 if( self::$add_script ) {
556 $script_url = esc_url_raw( plugins_url( 'js/polldaddy-shortcode.js', __FILE__ ) );
557
558 // if the script hasn't been loaded, load it
559 // if the script loads successfully, fire an 'pd-script-load' event
560 echo <<<SCRIPT
561 <script type='text/javascript'>
562 //<![CDATA[
563 ( function( d, c, j ) {
564 if ( !d.getElementById( j ) ) {
565 var pd = d.createElement( c ), s;
566 pd.id = j;
567 pd.async = true;
568 pd.src = '{$script_url}';
569 s = d.getElementsByTagName( c )[0];
570 s.parentNode.insertBefore( pd, s );
571 } else if ( typeof jQuery !== 'undefined' ) {
572 jQuery( d.body ).trigger( 'pd-script-load' );
573 }
574 } ( document, 'script', 'pd-polldaddy-loader' ) );
575 //]]>
576 </script>
577 SCRIPT;
578
579 }
580 }
581 }
582
583 // kick it all off
584 new CrowdsignalShortcode();
585
586 if ( ! function_exists( 'crowdsignal_link' ) ) {
587 // http://polldaddy.com/poll/1562975/?view=results&msg=voted
588 function crowdsignal_link( $content ) {
589 if ( Jetpack_AMP_Support::is_amp_request() ) {
590 return $content;
591 }
592
593 return preg_replace( '!(?:\n|\A)https?://(polldaddy\.com/poll|poll\.fm)/([0-9]+?)(/.*)?(?:\n|\Z)!i', "\n<script type='text/javascript' charset='utf-8' src='//static.polldaddy.com/p/$2.js'></script><noscript> <a href='https://poll.fm/$2'>View Poll</a></noscript>\n", $content );
594 }
595
596 // higher priority because we need it before auto-link and autop get to it
597 add_filter( 'the_content', 'crowdsignal_link', 1 );
598 add_filter( 'the_content_rss', 'crowdsignal_link', 1 );
599 }
600
601 /**
602 * Note that Core has the oembed of '#https?://survey\.fm/.*#i' as of 5.1.
603 * This should be removed after Core has the current regex is in our minimum version.
604 *
605 * @see https://core.trac.wordpress.org/ticket/46467
606 * @todo Confirm patch landed and remove once 5.2 is the minimum version.
607 */
608 wp_oembed_add_provider( '#https?://.+\.survey\.fm/.*#i', 'https://api.crowdsignal.com/oembed', true );
609
610 }
611