PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 10.1.1
Jetpack – WP Security, Backup, Speed, & Growth v10.1.1
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 14.3.1 14.4.2 All 500 releases
jetpack / modules / publicize / ui.php
ui.php
658 lines 20.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Only user facing pieces of Publicize are found here.
5 */
6 class Publicize_UI {
7
8 /**
9 * Contains an instance of class 'publicize' which loads Keyring, sets up services, etc.
10 */
11 public $publicize;
12
13 /**
14 * @var string URL to Sharing settings page in wordpress.com
15 */
16 protected $publicize_settings_url = '';
17
18 /**
19 * Hooks into WordPress to display the various pieces of UI and load our assets
20 */
21 function __construct() {
22 global $publicize;
23
24 $this->publicize = $publicize = new Publicize;
25
26 add_action( 'init', array( $this, 'init' ) );
27 }
28
29 function init() {
30 $this->publicize_settings_url = publicize_calypso_url();
31
32 // Show only to users with the capability required to manage their Publicize connections.
33 if ( ! $this->publicize->current_user_can_access_publicize_data() ) {
34 return;
35 }
36
37 // assets (css, js)
38 if ( $this->in_jetpack ) {
39 add_action( 'load-settings_page_sharing', array( $this, 'load_assets' ) );
40 }
41 add_action( 'admin_head-post.php', array( $this, 'post_page_metabox_assets' ) );
42 add_action( 'admin_head-post-new.php', array( $this, 'post_page_metabox_assets' ) );
43
44 // management of publicize (sharing screen, ajax/lightbox popup, and metabox on post screen)
45 add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page' ) );
46 add_action( 'post_submitbox_misc_actions', array( $this, 'post_page_metabox' ) );
47 }
48
49 /**
50 * If the ShareDaddy plugin is not active we need to add the sharing settings page to the menu still
51 */
52 function sharing_menu() {
53 add_submenu_page(
54 'options-general.php',
55 esc_html__( 'Sharing Settings', 'jetpack' ),
56 esc_html__( 'Sharing', 'jetpack' ),
57 'publish_posts',
58 'sharing',
59 array( $this, 'wrapper_admin_page' )
60 );
61 }
62
63 function wrapper_admin_page() {
64 Jetpack_Admin_Page::wrap_ui( array( $this, 'management_page' ) );
65 }
66
67 /**
68 * Management page to load if Sharedaddy is not active so the 'pre_admin_screen_sharing' action exists.
69 */
70 function management_page() { ?>
71 <div class="wrap">
72 <div class="icon32" id="icon-options-general"><br /></div>
73 <h1><?php esc_html_e( 'Sharing Settings', 'jetpack' ); ?></h1>
74
75 <?php
76 /** This action is documented in modules/sharedaddy/sharing.php */
77 do_action( 'pre_admin_screen_sharing' );
78 ?>
79
80 </div> <?php
81 }
82
83 /**
84 * styling for the sharing screen and popups
85 * JS for the options and switching
86 */
87 function load_assets() {
88 Jetpack_Admin_Page::load_wrapper_styles();
89 }
90
91 /**
92 * Lists the current user's publicized accounts for the blog
93 * looks exactly like Publicize v1 for now, UI and functionality updates will come after the move to keyring
94 */
95 function admin_page() {
96 ?>
97 <h2 id="publicize"><?php esc_html_e( 'Publicize', 'jetpack' ) ?></h2>
98 <p><?php esc_html_e( 'Connect social media services to automatically share new posts.', 'jetpack' ) ?></p>
99 <h4><?php
100 printf(
101 wp_kses(
102 __( "We've made some updates to Publicize. Please visit the <a href='%s' class='jptracks' data-jptracks-name='legacy_publicize_settings'>WordPress.com sharing page</a> to manage your publicize connections or use the button below.", 'jetpack' ),
103 array( 'a' => array( 'href' => array(), 'class' => array(), 'data-jptracks-name' => array() ) )
104 ),
105 esc_url( publicize_calypso_url() )
106 );
107 ?>
108 </h4>
109
110 <a href="<?php echo esc_url( publicize_calypso_url() ); ?>" class="button button-primary jptracks" data-jptracks-name='legacy_publicize_settings'><?php esc_html_e( 'Publicize Settings', 'jetpack' ); ?></a>
111 <?php
112 }
113
114 /**
115 * CSS for styling the publicize message box and counter that displays on the post page.
116 * There is also some JavaScript for length counting and some basic display effects.
117 */
118 function post_page_metabox_assets() {
119 global $post;
120 $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
121
122 $default_prefix = $this->publicize->default_prefix;
123 $default_prefix = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_prefix ) );
124
125 $default_message = $this->publicize->default_message;
126 $default_message = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_message ) );
127
128 $default_suffix = $this->publicize->default_suffix;
129 $default_suffix = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_suffix ) );
130
131 $max_length = defined( 'JETPACK_PUBLICIZE_TWITTER_LENGTH' ) ? JETPACK_PUBLICIZE_TWITTER_LENGTH : 280;
132 $max_length = $max_length - 24; // t.co link, space
133
134 ?>
135
136 <script type="text/javascript">
137 jQuery( function($) {
138 var wpasTitleCounter = $( '#wpas-title-counter' ),
139 wpasTwitterCheckbox = $( '.wpas-submit-twitter' ).length,
140 postTitle = $( '#title' ),
141 wpasTitle = $( '#wpas-title' ).keyup( function() {
142 var postTitleVal,
143 length = wpasTitle.val().length;
144
145 if ( ! length ) {
146 length = wpasTitle.attr( 'placeholder' ).length;
147 }
148
149 wpasTitleCounter.text( length ).trigger( 'change' );
150 } ),
151 authClick = false;
152
153 wpasTitleCounter.on( 'change', function( e ) {
154 if ( wpasTwitterCheckbox && parseInt( $( e.currentTarget ).text(), 10 ) > <?php echo (int) $max_length; ?> ) {
155 wpasTitleCounter.addClass( 'wpas-twitter-length-limit' );
156 } else {
157 wpasTitleCounter.removeClass( 'wpas-twitter-length-limit' );
158 }
159 } );
160
161 // Keep the postTitle and the placeholder in sync
162 postTitle.on( 'keyup', function( e ) {
163 var url = $( '#sample-permalink' ).text();
164 var defaultMessage = $.trim( '<?php printf( $default_prefix, 'url' ); printf( $default_message, 'e.currentTarget.value', 'url' ); printf( $default_suffix, 'url' ); ?>' )
165 .replace( /<[^>]+>/g,'');
166
167 wpasTitle.attr( 'placeholder', defaultMessage );
168 wpasTitle.trigger( 'keyup' );
169 } );
170
171 // set the initial placeholder
172 postTitle.trigger( 'keyup' );
173
174 // If a custom message has been provided, open the UI so the author remembers
175 if ( wpasTitle.val() && ! wpasTitle.prop( 'disabled' ) && wpasTitle.attr( 'placeholder' ) !== wpasTitle.val() ) {
176 $( '#publicize-form' ).show();
177 $( '#publicize-defaults' ).hide();
178 $( '#publicize-form-edit' ).hide();
179 }
180
181 $('#publicize-disconnected-form-show').click( function() {
182 $('#publicize-form').slideDown( 'fast' );
183 $(this).hide();
184 } );
185
186 $('#publicize-disconnected-form-hide').click( function() {
187 $('#publicize-form').slideUp( 'fast' );
188 $('#publicize-disconnected-form-show').show();
189 } );
190
191 $('#publicize-form-edit').click( function() {
192 $('#publicize-form').slideDown( 'fast', function() {
193 var selBeg = 0, selEnd = 0;
194 wpasTitle.focus();
195
196 if ( ! wpasTitle.text() ) {
197 wpasTitle.text( wpasTitle.attr( 'placeholder' ) );
198
199 selBeg = wpasTitle.text().indexOf( postTitle.val() );
200 if ( selBeg < 0 ) {
201 selBeg = 0;
202 } else {
203 selEnd = selBeg + postTitle.val().length;
204 }
205
206 var domObj = wpasTitle.get(0);
207 if ( domObj.setSelectionRange ) {
208 domObj.setSelectionRange( selBeg, selEnd );
209 } else if ( domObj.createTextRange ) {
210 var r = domObj.createTextRange();
211 r.moveStart( 'character', selBeg );
212 r.moveEnd( 'character', selEnd );
213 r.select();
214 }
215 }
216 } );
217
218 $('#publicize-defaults').hide();
219 $(this).hide();
220 return false;
221 } );
222
223 $('#publicize-form-hide').click( function() {
224 var newList = $.map( $('#publicize-form').slideUp( 'fast' ).find( ':checked' ), function( el ) {
225 return $.trim( $(el).parent( 'label' ).text() );
226 } );
227 $('#publicize-defaults').html( '<strong>' + newList.join( '</strong>, <strong>' ) + '</strong>' ).show();
228 $('#publicize-form-edit').show();
229 return false;
230 } );
231
232 $('.authorize-link').click( function() {
233 if ( authClick ) {
234 return false;
235 }
236 authClick = true;
237 $(this).after( '<img src="images/loading.gif" class="alignleft" style="margin: 0 .5em" />' );
238 $.ajaxSetup( { async: false } );
239
240 if ( window.wp && window.wp.autosave ) {
241 window.wp.autosave.server.triggerSave();
242 } else {
243 autosave();
244 }
245
246 return true;
247 } );
248
249 $( '.pub-service' ).click( function() {
250 var service = $(this).data( 'service' ),
251 fakebox = '<input id="wpas-submit-' + service + '" type="hidden" value="1" name="wpas[submit][' + service + ']" />';
252 $( '#add-publicize-check' ).append( fakebox );
253 } );
254
255 publicizeConnTestStart = function() {
256 $( '#pub-connection-tests' )
257 .removeClass( 'below-h2' )
258 .removeClass( 'error' )
259 .removeClass( 'publicize-token-refresh-message' )
260 .addClass( 'test-in-progress' )
261 .html( '' );
262 $.post( ajaxurl, { action: 'test_publicize_conns' }, publicizeConnTestComplete );
263 }
264
265 publicizeConnRefreshClick = function( event ) {
266 event.preventDefault();
267 var popupURL = event.currentTarget.href;
268 var popupTitle = event.currentTarget.title;
269 // open a popup window
270 // when it is closed, kick off the tests again
271 var popupWin = window.open( popupURL, popupTitle, '' );
272 var popupWinTimer= window.setInterval( function() {
273 if ( popupWin.closed !== false ) {
274 window.clearInterval( popupWinTimer );
275 publicizeConnTestStart();
276 }
277 }, 500 );
278 }
279
280 publicizeConnTestComplete = function( response ) {
281 var testsSelector = $( '#pub-connection-tests' );
282 testsSelector
283 .removeClass( 'test-in-progress' )
284 .removeClass( 'below-h2' )
285 .removeClass( 'error' )
286 .removeClass( 'publicize-token-refresh-message' )
287 .html( '' );
288
289 // If any of the tests failed, show some stuff
290 var somethingShownAlready = false;
291 var facebookNotice = false;
292 $.each( response.data, function( index, testResult ) {
293 // find the li for this connection
294 if ( ! testResult.connectionTestPassed && testResult.userCanRefresh ) {
295 if ( ! somethingShownAlready ) {
296 testsSelector
297 .addClass( 'below-h2' )
298 .addClass( 'error' )
299 .addClass( 'publicize-token-refresh-message' )
300 .append( "<p><?php echo esc_html( __( 'Before you hit Publish, please refresh the following connection(s) to make sure we can Publicize your post:', 'jetpack' ) ); ?></p>" );
301 somethingShownAlready = true;
302 }
303
304 if ( testResult.userCanRefresh ) {
305 testsSelector.append( '<p/>' );
306 $( '<a/>', {
307 'class' : 'pub-refresh-button button',
308 'title' : testResult.refreshText,
309 'href' : testResult.refreshURL,
310 'text' : testResult.refreshText,
311 'target' : '_refresh_' + testResult.serviceName
312 } )
313 .appendTo( testsSelector.children().last() )
314 .click( publicizeConnRefreshClick );
315 }
316 }
317
318 if( ! testResult.connectionTestPassed && ! testResult.userCanRefresh ) {
319 $( '#wpas-submit-' + testResult.unique_id ).prop( "checked", false ).prop( "disabled", true );
320 if ( ! facebookNotice ) {
321 var message = '<p>'
322 + testResult.connectionTestMessage
323 + '</p><p>'
324 + ' <a class="button" href="<?php echo esc_url( $this->publicize_settings_url ); ?>" rel="noopener noreferrer" target="_blank">'
325 + '<?php echo esc_html( __( 'Update Your Sharing Settings' ,'jetpack' ) ); ?>'
326 + '</a>'
327 + '<p>';
328
329 testsSelector
330 .addClass( 'below-h2' )
331 .addClass( 'error' )
332 .addClass( 'publicize-token-refresh-message' )
333 .append( message );
334 facebookNotice = true;
335 }
336 }
337 } );
338 }
339
340 $( document ).ready( function() {
341 // If we have the #pub-connection-tests div present, kick off the connection test
342 if ( $( '#pub-connection-tests' ).length ) {
343 publicizeConnTestStart();
344 }
345 } );
346
347 } );
348 </script>
349
350 <style type="text/css">
351 #publicize {
352 line-height: 1.5;
353 }
354 #publicize ul {
355 margin: 4px 0 4px 6px;
356 }
357 #publicize li {
358 margin: 0;
359 }
360 #publicize textarea {
361 margin: 4px 0 0;
362 width: 100%
363 }
364 #publicize ul.not-connected {
365 list-style: square;
366 padding-left: 1em;
367 }
368 .publicize__notice-warning {
369 display: block;
370 padding: 7px 10px;
371 margin: 5px 0;
372 border-left-width: 4px;
373 border-left-style: solid;
374 font-size: 12px;
375 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
376 }
377 .publicize-external-link {
378 display: block;
379 text-decoration: none;
380 margin-top: 8px;
381 }
382 .publicize-external-link__text {
383 text-decoration: underline;
384 }
385 #publicize-title:before {
386 content: "\f237";
387 font: normal 20px/1 dashicons;
388 speak: none;
389 margin-left: -1px;
390 padding-right: 3px;
391 vertical-align: top;
392 -webkit-font-smoothing: antialiased;
393 color: #8c8f94;
394 }
395 .post-new-php .authorize-link, .post-php .authorize-link {
396 line-height: 1.5em;
397 }
398 .post-new-php .authorize-message, .post-php .authorize-message {
399 margin-bottom: 0;
400 }
401 #poststuff #publicize .updated p {
402 margin: .5em 0;
403 }
404 .wpas-twitter-length-limit {
405 color: red;
406 }
407 .publicize__notice-warning .dashicons {
408 font-size: 16px;
409 text-decoration: none;
410 }
411 </style><?php
412 }
413
414 /**
415 * @param string $service_label Service's human-readable Label ("Facebook", "Twitter", ...)
416 * @param string $display_name Connection's human-readable Username ("@jetpack", ...)
417 * @return string
418 */
419 private function connection_label( $service_label, $display_name ) {
420 return sprintf(
421 /* translators: %1$s: Service Name (Facebook, Twitter, ...), %2$s: Username on Service (@jetpack, ...) */
422 __( '%1$s: %2$s', 'jetpack' ),
423 $service_label,
424 $display_name
425 );
426 }
427
428 /**
429 * Extracts the connections that require reauthentication, for example, LinkedIn, when it switched v1 to v2 of its API.
430 *
431 * @return array Connections that must be reauthenticated
432 */
433 function get_must_reauth_connections() {
434 $must_reauth = array();
435 $connections = $this->publicize->get_connections( 'linkedin' );
436 if ( is_array( $connections ) ) {
437 foreach ( $connections as $index => $connection ) {
438 if ( $this->publicize->is_invalid_linkedin_connection( $connection ) ) {
439 $must_reauth[ $index ] = 'LinkedIn';
440 }
441 }
442 }
443 return $must_reauth;
444 }
445
446 /**
447 * Controls the metabox that is displayed on the post page
448 * Allows the user to customize the message that will be sent out to the social network, as well as pick which
449 * networks to publish to. Also displays the character counter and some other information.
450 */
451 function post_page_metabox() {
452 global $post;
453
454 if ( ! $this->publicize->post_type_is_publicizeable( $post->post_type ) )
455 return;
456
457 $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
458 $connections_data = $this->publicize->get_filtered_connection_data();
459
460 $available_services = $this->publicize->get_services( 'all' );
461
462 if ( ! is_array( $available_services ) )
463 $available_services = array();
464
465 if ( ! is_array( $connections_data ) )
466 $connections_data = array();
467 ?>
468 <div id="publicize" class="misc-pub-section misc-pub-section-last">
469 <span id="publicize-title">
470 <?php
471 esc_html_e( 'Publicize:', 'jetpack' );
472
473 if ( 0 < count( $connections_data ) ) :
474 $publicize_form = $this->get_metabox_form_connected( $connections_data );
475
476 $must_reauth = $this->get_must_reauth_connections();
477 if ( ! empty( $must_reauth ) ) {
478 foreach ( $must_reauth as $connection_name ) {
479 ?>
480 <span class="notice-warning publicize__notice-warning">
481 <?php
482 /* translators: %s is the name of a Pubilicize service like "LinkedIn" */
483 printf( esc_html__(
484 'Your %s connection needs to be reauthenticated to continue working – head to Sharing to take care of it.',
485 'jetpack'
486 ), $connection_name );
487 ?>
488 <a
489 class="publicize-external-link"
490 href="<?php echo publicize_calypso_url() ?>"
491 target="_blank"
492 >
493 <span class="publicize-external-link__text"><?php esc_html_e( 'Go to Sharing settings', 'jetpack' ); ?></span>
494 <span class="dashicons dashicons-external"></span>
495 </a>
496 </span>
497 <?php
498 }
499 ?>
500 <?php
501 }
502
503 $labels = array();
504 foreach ( $connections_data as $connection_data ) {
505 if ( ! $connection_data['enabled'] ) {
506 continue;
507 }
508
509 $labels[] = sprintf(
510 '<strong>%s</strong>',
511 esc_html( $this->connection_label( $connection_data['service_label'], $connection_data['display_name'] ) )
512 );
513 }
514
515 ?>
516 <span id="publicize-defaults"><?php echo join( ', ', $labels ); ?></span>
517 <a href="#" id="publicize-form-edit"><?php esc_html_e( 'Edit', 'jetpack' ); ?></a>&nbsp;<a href="<?php echo esc_url( $this->publicize_settings_url ); ?>" rel="noopener noreferrer" target="_blank"><?php _e( 'Settings', 'jetpack' ); ?></a><br />
518 <?php
519
520 else :
521 $publicize_form = $this->get_metabox_form_disconnected( $available_services );
522
523 ?>
524 <strong><?php echo __( 'Not Connected', 'jetpack' ); ?></strong>
525 <a href="#" id="publicize-disconnected-form-show"><?php esc_html_e( 'Edit', 'jetpack' ); ?></a><br />
526 <?php
527
528 endif;
529 ?>
530 </span>
531 <?php
532 /**
533 * Filter the Publicize details form.
534 *
535 * @module publicize
536 *
537 * @since 2.0.0
538 *
539 * @param string $publicize_form Publicize Details form appearing above Publish button in the editor.
540 */
541 echo apply_filters( 'publicize_form', $publicize_form );
542 ?>
543 </div> <?php // #publicize
544 }
545
546 /**
547 * Generates HTML content for connections form.
548 *
549 * @since 6.7
550 *
551 * @global WP_Post $post The current post instance being published.
552 *
553 * @param array $connections_data
554 *
555 * @return array {
556 * Array of content for generating connection form.
557 *
558 * @type string HTML content of form
559 * @type array {
560 * Array of connection labels for active connections only.
561 *
562 * @type string Connection label string.
563 * }
564 * }
565 */
566 private function get_metabox_form_connected( $connections_data ) {
567 global $post;
568
569 $all_done = $this->publicize->post_is_done_sharing();
570 $all_connections_done = true;
571
572 ob_start();
573
574 ?>
575 <div id="publicize-form" class="hide-if-js">
576 <ul>
577 <?php
578
579 foreach ( $connections_data as $connection_data ) {
580 $all_connections_done = $all_connections_done && $connection_data['done'];
581 ?>
582
583 <li>
584 <label for="wpas-submit-<?php echo esc_attr( $connection_data['unique_id'] ); ?>">
585 <input
586 type="checkbox"
587 name="wpas[submit][<?php echo esc_attr( $connection_data['unique_id'] ); ?>]"
588 id="wpas-submit-<?php echo esc_attr( $connection_data['unique_id'] ); ?>"
589 class="wpas-submit-<?php echo esc_attr( $connection_data['service_name'] ); ?>"
590 value="1"
591 <?php
592 checked( true, $connection_data['enabled'] );
593 disabled( false, $connection_data['toggleable'] );
594 ?>
595 />
596 <?php if ( $connection_data['enabled'] && ! $connection_data['toggleable'] ) : // Need to submit a value to force a global connection to POST ?>
597 <input
598 type="hidden"
599 name="wpas[submit][<?php echo esc_attr( $connection_data['unique_id'] ); ?>]"
600 value="1"
601 />
602 <?php endif; ?>
603
604 <?php echo esc_html( $this->connection_label( $connection_data['service_label'], $connection_data['display_name'] ) ); ?>
605
606 </label>
607 </li>
608 <?php
609 }
610
611 $title = get_post_meta( $post->ID, $this->publicize->POST_MESS, true );
612 if ( ! $title ) {
613 $title = '';
614 }
615
616 $all_done = $all_done || $all_connections_done;
617
618 ?>
619
620 </ul>
621
622 <label for="wpas-title"><?php _e( 'Custom Message:', 'jetpack' ); ?></label>
623 <span id="wpas-title-counter" class="alignright hide-if-no-js">0</span>
624 <textarea name="wpas_title" id="wpas-title"<?php disabled( $all_done ); ?>><?php echo esc_textarea( $title ); ?></textarea>
625 <a href="#" class="hide-if-no-js button" id="publicize-form-hide"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
626 <input type="hidden" name="wpas[0]" value="1" />
627 </div>
628
629 <?php if ( ! $all_done ) : ?>
630 <div id="pub-connection-tests"></div>
631 <?php endif; ?>
632 <?php // #publicize-form
633
634 return ob_get_clean();
635 }
636
637 private function get_metabox_form_disconnected( $available_services ) {
638 ob_start();
639 ?><div id="publicize-form" class="hide-if-js">
640 <div id="add-publicize-check" style="display: none;"></div>
641
642 <?php _e( 'Connect to', 'jetpack' ); ?>:
643
644 <ul class="not-connected">
645 <?php foreach ( $available_services as $service_name => $service ) : ?>
646 <li>
647 <a class="pub-service" data-service="<?php echo esc_attr( $service_name ); ?>" title="<?php echo esc_attr( sprintf( __( 'Connect and share your posts on %s', 'jetpack' ), $this->publicize->get_service_label( $service_name ) ) ); ?>" rel="noopener noreferrer" target="_blank" href="<?php echo esc_url( $this->publicize->connect_url( $service_name ) ); ?>">
648 <?php echo esc_html( $this->publicize->get_service_label( $service_name ) ); ?>
649 </a>
650 </li>
651 <?php endforeach; ?>
652 </ul>
653 <a href="#" class="hide-if-no-js button" id="publicize-disconnected-form-hide"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
654 </div><?php // #publicize-form
655 return ob_get_clean();
656 }
657 }
658