PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 9.7.2
Jetpack – WP Security, Backup, Speed, & Growth v9.7.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 14.3.1 All 501 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