PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-publicize/src/class-publicize-ui.php +543 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,543 @@
1 +<?php
2 +/**
3 + * Publicize_UI class.
4 + *
5 + * @package automattic/jetpack-publicize
6 + */
7 +
8 +namespace Automattic\Jetpack\Publicize;
9 +
10 +use Automattic\Jetpack\Assets;
11 +use Automattic\Jetpack\Current_Plan;
12 +use Automattic\Jetpack\Publicize\Publicize_Utils as Utils;
13 +use Automattic\Jetpack\Status\Host;
14 +
15 +/**
16 + * Classic editor integration: the Publicize metabox on the post screen, and its assets.
17 + */
18 +class Publicize_UI {
19 + /**
20 + * Contains an instance of class 'Publicize' which loads Keyring, sets up services, etc.
21 + *
22 + * @var Publicize Instance of Publicize
23 + */
24 + public $publicize;
25 +
26 + /**
27 + * URL of the admin page where Publicize connections are managed.
28 + *
29 + * @var string
30 + */
31 + protected $publicize_settings_url = '';
32 +
33 + /**
34 + * Hooks into WordPress to display the various pieces of UI and load our assets
35 + */
36 + public function __construct() {
37 + global $publicize;
38 + if ( ! is_object( $publicize ) ) {
39 + $publicize = new Publicize();
40 + }
41 + $this->publicize = $publicize;
42 +
43 + add_action( 'admin_init', array( $this, 'init' ) );
44 + }
45 +
46 + /**
47 + * Initialize UI-related functionality.
48 + */
49 + public function init() {
50 + // Show only to users with the capability required to manage their Publicize connections.
51 + if ( ! Utils::is_publicize_active() || ! $this->publicize->current_user_can_access_publicize_data() ) {
52 + return;
53 + }
54 +
55 + $this->publicize_settings_url = $this->publicize->publicize_connections_url();
56 +
57 + // Assets (css, js).
58 + add_action( 'admin_head-post.php', array( $this, 'post_page_metabox_assets' ) );
59 + add_action( 'admin_head-post-new.php', array( $this, 'post_page_metabox_assets' ) );
60 +
61 + add_action( 'post_submitbox_misc_actions', array( $this, 'post_page_metabox' ) );
62 + }
63 +
64 + /**
65 + * CSS for styling the publicize message box and counter that displays on the post page.
66 + * There is also some JavaScript for length counting and some basic display effects.
67 + */
68 + public function post_page_metabox_assets() {
69 + // We don't need those assets for the block editor pages.
70 + $current_screen = get_current_screen();
71 + if ( $current_screen && $current_screen->is_block_editor ) {
72 + return;
73 + }
74 +
75 + $is_atomic_site = ( new Host() )->is_woa_site();
76 + $is_simple_site = ( new Host() )->is_wpcom_simple();
77 + $site_type = $is_atomic_site ? 'atomic' : ( $is_simple_site ? 'simple' : 'jetpack' );
78 +
79 + Assets::register_script(
80 + 'jetpack-social-classic-editor-options',
81 + '../build/classic-editor.js',
82 + __FILE__,
83 + array(
84 + 'in_footer' => true,
85 + 'enqueue' => true,
86 + 'textdomain' => 'jetpack-publicize-pkg',
87 + )
88 + );
89 +
90 + wp_add_inline_script(
91 + 'jetpack-social-classic-editor-options',
92 + 'var jetpackSocialClassicEditorOptions = ' . wp_json_encode(
93 + array(
94 + 'connectionsUrl' => esc_url( $this->publicize_settings_url ),
95 + 'isEnhancedPublishingEnabled' => $this->publicize->has_enhanced_publishing_feature(),
96 + 'resharePath' => '/wpcom/v2/publicize/share-post/{postId}',
97 + 'refreshConnections' => '/wpcom/v2/publicize/connections?test_connections=1',
98 + 'isReshareSupported' => Current_Plan::supports( 'republicize' ),
99 + 'siteType' => $site_type,
100 + ),
101 + JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP
102 + ),
103 + 'before'
104 + );
105 +
106 + $default_prefix = $this->publicize->default_prefix;
107 + $default_prefix = preg_replace( '/%([0-9])\$s/', '" + %\\1$s + "', wp_json_encode( (string) $default_prefix, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) );
108 +
109 + $default_message = $this->publicize->default_message;
110 + $default_message = preg_replace( '/%([0-9])\$s/', '" + %\\1$s + "', wp_json_encode( (string) $default_message, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) );
111 +
112 + $default_suffix = $this->publicize->default_suffix;
113 + $default_suffix = preg_replace( '/%([0-9])\$s/', '" + %\\1$s + "', wp_json_encode( (string) $default_suffix, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) );
114 +
115 + $max_length = defined( 'JETPACK_PUBLICIZE_TWITTER_LENGTH' ) ? JETPACK_PUBLICIZE_TWITTER_LENGTH : 280;
116 + $max_length -= 24; // t.co link, space.
117 +
118 + ?>
119 +
120 +<script type="text/javascript">
121 +jQuery( function($) {
122 + var wpasTitleCounter = $( '#wpas-title-counter' ),
123 + wpasTwitterCheckbox = $( '.wpas-submit-twitter' ).length,
124 + postTitle = $( '#title' ),
125 + wpasTitle = $( '#wpas-title' ).keyup( function() {
126 + var postTitleVal,
127 + length = wpasTitle.val().length;
128 +
129 + if ( ! length ) {
130 + length = wpasTitle.attr( 'placeholder' ).length;
131 + }
132 +
133 + wpasTitleCounter.text( length ).trigger( 'change' );
134 + } ),
135 + authClick = false;
136 +
137 + wpasTitleCounter.on( 'change', function( e ) {
138 + if ( wpasTwitterCheckbox && parseInt( $( e.currentTarget ).text(), 10 ) > <?php echo (int) $max_length; ?> ) {
139 + wpasTitleCounter.addClass( 'wpas-twitter-length-limit' );
140 + } else {
141 + wpasTitleCounter.removeClass( 'wpas-twitter-length-limit' );
142 + }
143 + } );
144 +
145 + // Keep the postTitle and the placeholder in sync
146 + postTitle.on( 'keyup', function( e ) {
147 + var url = $( '#sample-permalink' ).text();
148 + <?php // phpcs:ignore ?>
149 + var defaultMessage = $.trim( <?php printf( $default_prefix, 'url' ); ?> + <?php printf( $default_message, 'e.currentTarget.value', 'url' ); ?> + <?php printf( $default_suffix, 'url' ); ?> )
150 + .replace( /<[^>]+>/g,'');
151 +
152 + wpasTitle.attr( 'placeholder', defaultMessage );
153 + wpasTitle.trigger( 'keyup' );
154 + } );
155 +
156 + // set the initial placeholder
157 + postTitle.trigger( 'keyup' );
158 +
159 + // If a custom message has been provided, open the UI so the author remembers
160 + if ( wpasTitle.val() && ! wpasTitle.prop( 'disabled' ) && wpasTitle.attr( 'placeholder' ) !== wpasTitle.val() ) {
161 + $( '#publicize-form' ).show();
162 + $( '#publicize-defaults' ).hide();
163 + $( '#publicize-form-edit' ).hide();
164 + }
165 +
166 + $('#publicize-disconnected-form-show').click( function() {
167 + $('#publicize-form').slideDown( 'fast' );
168 + $(this).hide();
169 + } );
170 +
171 + $('#publicize-disconnected-form-hide').click( function() {
172 + $('#publicize-form').slideUp( 'fast' );
173 + $('#publicize-disconnected-form-show').show();
174 + } );
175 +
176 + $('#publicize-form-edit').click( function() {
177 + $('#publicize-form').slideDown( 'fast', function() {
178 + var selBeg = 0, selEnd = 0;
179 + wpasTitle.focus();
180 +
181 + if ( ! wpasTitle.text() ) {
182 + wpasTitle.text( wpasTitle.attr( 'placeholder' ) );
183 +
184 + selBeg = wpasTitle.text().indexOf( postTitle.val() );
185 + if ( selBeg < 0 ) {
186 + selBeg = 0;
187 + } else {
188 + selEnd = selBeg + postTitle.val().length;
189 + }
190 +
191 + var domObj = wpasTitle.get(0);
192 + if ( domObj.setSelectionRange ) {
193 + domObj.setSelectionRange( selBeg, selEnd );
194 + } else if ( domObj.createTextRange ) {
195 + var r = domObj.createTextRange();
196 + r.moveStart( 'character', selBeg );
197 + r.moveEnd( 'character', selEnd );
198 + r.select();
199 + }
200 + }
201 + } );
202 +
203 + $('#publicize-defaults').hide();
204 + $(this).hide();
205 + return false;
206 + } );
207 +
208 +
209 + $('#publicize-form-hide').click( function() {
210 + var newList = $.map( $('#publicize-form').slideUp( 'fast' ).find( ':checked' ), function( el ) {
211 + return $.trim( $(el).parent( 'label' ).text() );
212 + } );
213 + $('#publicize-defaults').html( '<strong>' + newList.join( '</strong>, <strong>' ) + '</strong>' ).show();
214 + $('#publicize-form-edit').show();
215 + return false;
216 + } );
217 +
218 + $('.authorize-link').click( function() {
219 + if ( authClick ) {
220 + return false;
221 + }
222 + authClick = true;
223 + $(this).after( '<img src="images/loading.gif" class="alignleft" style="margin: 0 .5em" />' );
224 + $.ajaxSetup( { async: false } );
225 +
226 + if ( window.wp && window.wp.autosave ) {
227 + window.wp.autosave.server.triggerSave();
228 + } else {
229 + autosave();
230 + }
231 +
232 + return true;
233 + } );
234 +
235 + $( '.pub-service' ).click( function() {
236 + var service = $(this).data( 'service' ),
237 + fakebox = '<input id="wpas-submit-' + service + '" type="hidden" value="1" name="wpas[submit][' + service + ']" />';
238 + $( '#add-publicize-check' ).append( fakebox );
239 + } );
240 +} );
241 +</script>
242 +
243 +<style type="text/css">
244 +#publicize {
245 + line-height: 1.5;
246 +}
247 +#publicize ul {
248 + margin: 4px 0 4px 6px;
249 +}
250 +#publicize li {
251 + margin: 0;
252 +}
253 +#publicize textarea {
254 + margin: 4px 0 0;
255 + width: 100%
256 +}
257 +#publicize ul.not-connected {
258 + list-style: square;
259 + padding-left: 1em;
260 +}
261 +.wpas-disabled {
262 + color: #999;
263 +}
264 +.publicize__notice-warning {
265 + display: block;
266 + padding: 7px 10px;
267 + margin: 5px 0;
268 + border-left-width: 4px;
269 + border-left-style: solid;
270 + font-size: 12px;
271 + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
272 +}
273 +.publicize__notice-media-warning {
274 + border-right: 1px solid #c3c4c7;
275 + border-bottom: 1px solid #c3c4c7;
276 + border-top: 1px solid #c3c4c7;
277 +}
278 +.publicize-external-link {
279 + display: block;
280 + text-decoration: none;
281 + margin-top: 8px;
282 +}
283 +.publicize-external-link__text {
284 + text-decoration: underline;
285 +}
286 +#publicize-title::before {
287 + content: "\f237";
288 + font: normal 20px/1 dashicons;
289 + speak: none;
290 + margin-left: -1px;
291 + padding-right: 3px;
292 + vertical-align: top;
293 + -webkit-font-smoothing: antialiased;
294 + color: #8c8f94;
295 +}
296 +.post-new-php .authorize-link, .post-php .authorize-link {
297 + line-height: 1.5em;
298 +}
299 +.post-new-php .authorize-message, .post-php .authorize-message {
300 + margin-bottom: 0;
301 +}
302 +#poststuff #publicize .updated p {
303 + margin: .5em 0;
304 +}
305 +.wpas-twitter-length-limit {
306 + color: red;
307 +}
308 +.publicize__notice-warning .dashicons {
309 + font-size: 16px;
310 + text-decoration: none;
311 +}
312 +.publicize-placeholders-help {
313 + margin: 0.5rem 0 1rem;
314 +}
315 +</style>
316 + <?php
317 + }
318 +
319 + /**
320 + * Get the connection label.
321 + *
322 + * @param string $service_label Service's human-readable Label ("Facebook", "Twitter", ...).
323 + * @param string $display_name Connection's human-readable Username ("@jetpack", ...).
324 + * @return string
325 + */
326 + private function connection_label( $service_label, $display_name ) {
327 + return sprintf(
328 + /* translators: %1$s: Service Name (Facebook, Twitter, ...), %2$s: Username on Service (@jetpack, ...) */
329 + __( '%1$s: %2$s', 'jetpack-publicize-pkg' ),
330 + $service_label,
331 + $display_name
332 + );
333 + }
334 +
335 + /**
336 + * Controls the metabox that is displayed on the post page
337 + * Allows the user to customize the message that will be sent out to the social network, as well as pick which
338 + * networks to publish to. Also displays the character counter and some other information.
339 + */
340 + public function post_page_metabox() {
341 + global $post;
342 +
343 + if ( ! $this->publicize->post_type_is_publicizeable( $post->post_type ) ) {
344 + return;
345 + }
346 +
347 + $connections_data = $this->publicize->get_filtered_connection_data();
348 +
349 + if ( ! is_array( $connections_data ) ) {
350 + $connections_data = array();
351 + }
352 + ?>
353 + <div id="publicize" class="misc-pub-section misc-pub-section-last">
354 + <span id="publicize-title">
355 + <?php
356 + esc_html_e( 'Jetpack Social:', 'jetpack-publicize-pkg' );
357 +
358 + if ( ! empty( $connections_data ) ) :
359 + $publicize_form = $this->get_metabox_form_connected( $connections_data );
360 +
361 + $labels = array();
362 +
363 + foreach ( $connections_data as $connection_data ) {
364 + if ( ! $connection_data['enabled'] ) {
365 + continue;
366 + }
367 +
368 + $labels[] = sprintf(
369 + '<strong>%s</strong>',
370 + esc_html( $this->connection_label( $connection_data['service_label'], $connection_data['display_name'] ) )
371 + );
372 + }
373 +
374 + ?>
375 + <?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- labels are already escaped above ?>
376 + <span id="publicize-defaults"><?php echo implode( ', ', $labels ); ?></span>
377 + <a href="#" id="publicize-form-edit"><?php esc_html_e( 'Edit', 'jetpack-publicize-pkg' ); ?></a>&nbsp;<a href="<?php echo esc_url( $this->publicize->publicize_connections_url() ); ?>" rel="noopener noreferrer" target="_blank"><?php esc_html_e( 'Settings', 'jetpack-publicize-pkg' ); ?></a><br />
378 + <?php
379 + else :
380 + $publicize_form = '';
381 + ?>
382 + <strong><?php esc_html_e( 'Not Connected', 'jetpack-publicize-pkg' ); ?></strong>
383 + <a href="<?php echo esc_url( $this->publicize->publicize_connections_url() ); ?>" rel="noopener noreferrer" target="_blank"><?php esc_html_e( 'Settings', 'jetpack-publicize-pkg' ); ?></a><br />
384 + <?php
385 +
386 + endif;
387 + ?>
388 + </span>
389 + <?php
390 + /**
391 + * Fires right before rendering the Publicize form in the Classic
392 + * Editor.
393 + *
394 + * @since 0.14.0
395 + */
396 + do_action( 'publicize_classic_editor_form_before' );
397 +
398 + /**
399 + * Filter the Publicize details form.
400 + *
401 + * @since 0.1.0
402 + * @since-jetpack 2.0.0
403 + *
404 + * @param string $publicize_form Publicize Details form appearing above Publish button in the editor.
405 + */
406 + echo apply_filters( 'publicize_form', $publicize_form ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Parts of the form are escaped individually in the code above.
407 +
408 + /**
409 + * Fires right after rendering the Publicize form in the Classic
410 + * Editor.
411 + *
412 + * @since 0.14.0
413 + */
414 + do_action( 'publicize_classic_editor_form_after' );
415 + ?>
416 + </div>
417 + <?php
418 + }
419 +
420 + /**
421 + * Generates HTML content for connections form.
422 + *
423 + * @since 0.1.0
424 + * @since-jetpack 6.7.0
425 + *
426 + * @global WP_Post $post The current post instance being published.
427 + *
428 + * @param array $connections_data Array of connections.
429 + * @return array {
430 + * Array of content for generating connection form.
431 + *
432 + * @type string HTML content of form
433 + * @type array {
434 + * Array of connection labels for active connections only.
435 + *
436 + * @type string Connection label string.
437 + * }
438 + * }
439 + */
440 + private function get_metabox_form_connected( $connections_data ) {
441 + global $post;
442 +
443 + ob_start();
444 +
445 + ?>
446 + <div id="publicize-form" class="hide-if-js">
447 + <ul>
448 + <?php
449 +
450 + foreach ( $connections_data as $connection_data ) {
451 + ?>
452 +
453 + <li>
454 + <label
455 + for="wpas-submit-<?php echo esc_attr( $connection_data['connection_id'] ); ?>"
456 + >
457 + <input
458 + type="checkbox"
459 + name="wpas[submit][<?php echo esc_attr( $connection_data['connection_id'] ); ?>]"
460 + id="wpas-submit-<?php echo esc_attr( $connection_data['connection_id'] ); ?>"
461 + class="wpas-submit-<?php echo esc_attr( $connection_data['service_name'] ); ?>"
462 + value="1"
463 + data-id="<?php echo esc_attr( $connection_data['connection_id'] ); ?>"
464 + <?php
465 + checked( true, $connection_data['enabled'] );
466 + ?>
467 + />
468 + <?php echo esc_html( $this->connection_label( $connection_data['service_label'], $connection_data['display_name'] ) ); ?>
469 +
470 + </label>
471 + </li>
472 + <?php
473 + }
474 +
475 + $title = get_post_meta( $post->ID, $this->publicize->POST_MESS, true );
476 + if ( ! $title ) {
477 + $title = '';
478 + }
479 +
480 + $is_social_note = 'jetpack-social-note' === get_post_type( $post->ID );
481 +
482 + $is_post_published = 'publish' === get_post_status( $post->ID );
483 +
484 + $templates_enabled = $this->publicize->has_paid_features();
485 +
486 + $placeholders = $this->get_message_placeholders();
487 +
488 + ?>
489 +
490 + </ul>
491 +
492 + <?php if ( ! $is_social_note ) : ?>
493 + <label for="wpas-title"><?php esc_html_e( 'Custom Message:', 'jetpack-publicize-pkg' ); ?></label>
494 + <?php if ( ! $templates_enabled ) : ?>
495 + <span id="wpas-title-counter" class="alignright hide-if-no-js">0</span>
496 + <?php endif; ?>
497 + <textarea name="wpas_title" id="wpas-title"><?php echo esc_textarea( $title ); ?></textarea>
498 + <?php if ( $templates_enabled && ! empty( $placeholders ) ) : ?>
499 + <details class="publicize-placeholders-help">
500 + <summary><?php esc_html_e( 'Available placeholders', 'jetpack-publicize-pkg' ); ?></summary>
501 + <p>
502 + <?php esc_html_e( 'Use placeholders to automatically insert post details.', 'jetpack-publicize-pkg' ); ?>
503 + </p>
504 + <ul>
505 + <?php foreach ( $placeholders as $placeholder ) : ?>
506 + <li>
507 + <code><?php echo esc_html( $placeholder['id'] ); ?></code>
508 + &mdash; <?php echo esc_html( $placeholder['label'] ); ?>
509 + </li>
510 + <?php endforeach; ?>
511 + </ul>
512 + </details>
513 + <?php endif; ?>
514 + <a href="#" class="hide-if-no-js button" id="publicize-form-hide"><?php esc_html_e( 'OK', 'jetpack-publicize-pkg' ); ?></a>
515 + <input type="hidden" name="wpas[0]" value="1" />
516 + <?php endif; ?>
517 + <?php if ( $is_post_published && Current_Plan::supports( 'republicize' ) ) : ?>
518 + <button type="button" class="hide-if-no-js button" id="publicize-share-now">
519 + <?php esc_html_e( 'Share now', 'jetpack-publicize-pkg' ); ?>
520 + </button>
521 + <span id="publicize-share-now-notice" class="hidden"></span>
522 + <?php endif; ?>
523 + </div>
524 +
525 + <div id="pub-connection-needs-media"></div>
526 + <div id="pub-connection-tests"></div>
527 + <?php
528 +
529 + return ob_get_clean();
530 + }
531 +
532 + /**
533 + * Get the catalogue of placeholders supported in custom Publicize messages.
534 + *
535 + * Sourced from WPCOM via `Message_Templates_Placeholders` so the metabox
536 + * hint can never drift from the resolver in `Template_Parser`.
537 + *
538 + * @return array<int, array{id: string, label: string}> Ordered list of placeholders.
539 + */
540 + private function get_message_placeholders() {
541 + return Message_Templates_Placeholders::get_all();
542 + }
543 +}