PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.5.1
Jetpack – WP Security, Backup, Speed, & Growth v7.5.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 / custom-post-types / comics.php
comics.php
534 lines 18.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Automattic\Jetpack\Assets;
4
5 class Jetpack_Comic {
6 const POST_TYPE = 'jetpack-comic';
7
8 static function init() {
9 static $instance = false;
10
11 if ( ! $instance )
12 $instance = new Jetpack_Comic();
13
14 return $instance;
15 }
16
17 /**
18 * Conditionally hook into WordPress.
19 *
20 * Themes must declare that they support this module by adding
21 * add_theme_support( 'jetpack-comic' ); during after_setup_theme.
22 *
23 * If no theme support is found there is no need to hook into
24 * WordPress. We'll just return early instead.
25 */
26 function __construct() {
27 // Make sure the post types are loaded for imports
28 add_action( 'import_start', array( $this, 'register_post_types' ) );
29
30 // Add to REST API post type whitelist
31 add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_rest_api_type' ) );
32
33 // If called via REST API, we need to register later in lifecycle
34 add_action( 'restapi_theme_init', array( $this, 'maybe_register_post_types' ) );
35
36 // Return early if theme does not support Jetpack Comic.
37 if ( ! ( $this->site_supports_comics() ) )
38 return;
39
40 $this->register_post_types();
41
42 add_action( 'pre_get_posts', array( $this, 'add_posts_to_loop' ) );
43
44 // In order for the Feedbag job to find Comic posts, we need to circumvent any pretty
45 // URLs in the RSS feed given to Feedbag in favor of /?p=123&post_type=jetpack-comic
46 add_filter( 'the_permalink_rss', array( $this, 'custom_permalink_for_feedbag' ) );
47
48 // There are some cases (like when Feedbag is fetching posts) that the comics
49 // post type needs to be registered no matter what, but none of the UI needs to be
50 // available.
51
52 add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
53
54 if ( function_exists( 'queue_publish_post' ) ) {
55 add_action( 'publish_jetpack-comic', 'queue_publish_post', 10, 2 );
56 }
57
58 add_action( 'pre_get_posts', array( $this, 'include_in_feeds' ) );
59
60 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
61
62 add_filter( 'manage_' . self::POST_TYPE . '_posts_columns', array( $this, 'manage_posts_columns' ) );
63 add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', array( $this, 'manage_posts_custom_column' ), 10, 2 );
64 add_image_size( 'jetpack-comic-thumb', 150, 0, false );
65
66 // Enable front-end uploading for users special enough.
67 if ( current_user_can( 'upload_files' ) && current_user_can( 'edit_posts' ) ) {
68 add_action( 'wp_ajax_jetpack_comic_upload', array( $this, 'upload' ) );
69 add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
70 }
71
72 /**
73 * Add a "Convert to Comic" and "Convert to Post" option to the bulk
74 * edit dropdowns.
75 */
76 add_action( 'admin_footer-edit.php', array( $this, 'admin_footer' ) );
77 add_action( 'load-edit.php', array( $this, 'bulk_edit' ) );
78 add_action( 'admin_notices', array( $this, 'bulk_edit_notices' ) );
79 }
80
81 public function admin_footer() {
82 $post_type = get_post_type();
83
84 ?>
85 <script type="text/javascript">
86 jQuery( document ).ready( function( $ ) {
87 <?php if ( ! $post_type || 'post' == $post_type ) { ?>
88 $( '<option>' )
89 .val( 'post2comic' )
90 .text( <?php echo json_encode( __( 'Convert to Comic', 'jetpack' ) ); ?> )
91 .appendTo( "select[name='action'], select[name='action2']" );
92 <?php } ?>
93 <?php if ( ! $post_type || self::POST_TYPE == $post_type ) { ?>
94 $( '<option>' )
95 .val( 'comic2post' )
96 .text( <?php echo json_encode( __( 'Convert to Post', 'jetpack' ) ); ?> )
97 .appendTo( "select[name='action'], select[name='action2']" );
98 <?php } ?>
99
100 $( '#message.jetpack-comic-post-type-conversion' ).remove().insertAfter( $( '.wrap h2:first' ) ).show();
101 });
102 </script>
103 <?php
104 }
105
106 /**
107 * Handle the "Convert to [Post|Comic]" bulk action.
108 */
109 public function bulk_edit() {
110 if ( empty( $_REQUEST['post'] ) )
111 return;
112
113 $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
114 $action = $wp_list_table->current_action();
115
116 check_admin_referer( 'bulk-posts' );
117
118 if ( 'post2comic' == $action || 'comic2post' == $action ) {
119 if ( ! current_user_can( 'publish_posts' ) )
120 wp_die( __( 'You are not allowed to make this change.', 'jetpack' ) );
121
122 $post_ids = array_map( 'intval', $_REQUEST['post'] );
123
124 $modified_count = 0;
125
126 foreach ( $post_ids as $post_id ) {
127 $destination_post_type = ( $action == 'post2comic' ) ? self::POST_TYPE : 'post';
128 $origin_post_type = ( $destination_post_type == 'post' ) ? self::POST_TYPE : 'post';
129
130 if ( current_user_can( 'edit_post', $post_id ) ) {
131 $post = get_post( $post_id );
132
133 // Only convert posts that are post => comic or comic => post.
134 // (e.g., Ignore comic => comic, page => post, etc. )
135 if ( $post->post_type != $destination_post_type && $post->post_type == $origin_post_type ) {
136 $post_type_object = get_post_type_object( $destination_post_type );
137
138 if ( current_user_can( $post_type_object->cap->publish_posts ) ) {
139 set_post_type( $post_id, $destination_post_type );
140 $modified_count++;
141 }
142 }
143 }
144 }
145
146 $sendback = remove_query_arg( array( 'exported', 'untrashed', 'deleted', 'ids' ), wp_get_referer() );
147
148 if ( ! $sendback )
149 $sendback = add_query_arg( array( 'post_type', get_post_type() ), admin_url( 'edit.php' ) );
150
151 $pagenum = $wp_list_table->get_pagenum();
152 $sendback = add_query_arg( array( 'paged' => $pagenum, 'post_type_changed' => $modified_count ), $sendback );
153
154 wp_safe_redirect( $sendback );
155 exit();
156 }
157 }
158
159 /**
160 * Show the post conversion success notice.
161 */
162 public function bulk_edit_notices() {
163 global $pagenow;
164
165 if ( 'edit.php' == $pagenow && ! empty( $_GET['post_type_changed'] ) ) {
166 ?><div id="message" class="updated below-h2 jetpack-comic-post-type-conversion" style="display: none;"><p><?php
167 printf( _n( 'Post converted.', '%s posts converted', $_GET['post_type_changed'], 'jetpack' ), number_format_i18n( $_GET['post_type_changed'] ) );
168 ?></p></div><?php
169 }
170 }
171
172 public function register_scripts() {
173 wp_enqueue_style( 'jetpack-comics-style', plugins_url( 'comics/comics.css', __FILE__ ) );
174 wp_style_add_data( 'jetpack-comics-style', 'rtl', 'replace' );
175 wp_enqueue_script(
176 'jetpack-comics',
177 Assets::get_file_url_for_environment(
178 '_inc/build/custom-post-types/comics/comics.min.js',
179 'modules/custom-post-types/comics/comics.js'
180 ),
181 array( 'jquery', 'jquery.spin' )
182 );
183
184 $options = array(
185 'nonce' => wp_create_nonce( 'jetpack_comic_upload_nonce' ),
186 'writeURL' => admin_url( 'admin-ajax.php?action=jetpack_comic_upload' ),
187 'labels' => array(
188 'dragging' => __( 'Drop images to upload', 'jetpack' ),
189 'uploading' => __( 'Uploading...', 'jetpack' ),
190 'processing' => __( 'Processing...', 'jetpack' ),
191 'unsupported' => __( "Sorry, your browser isn't supported. Upgrade at browsehappy.com.", 'jetpack' ),
192 'invalidUpload' => __( 'Only images can be uploaded here.', 'jetpack' ),
193 'error' => __( "Your upload didn't complete; try again later or cross your fingers and try again right now.", 'jetpack' ),
194 )
195 );
196
197 wp_localize_script( 'jetpack-comics', 'Jetpack_Comics_Options', $options );
198 }
199
200 public function admin_enqueue_scripts() {
201 wp_enqueue_style( 'jetpack-comics-admin', plugins_url( 'comics/admin.css', __FILE__ ) );
202 }
203
204 public function maybe_register_post_types() {
205 // Return early if theme does not support Jetpack Comic.
206 if ( ! ( $this->site_supports_comics() ) )
207 return;
208
209 $this->register_post_types();
210 }
211
212 function register_post_types() {
213 if ( post_type_exists( self::POST_TYPE ) ) {
214 return;
215 }
216
217 register_post_type( self::POST_TYPE, array(
218 'description' => __( 'Comics', 'jetpack' ),
219 'labels' => array(
220 'name' => esc_html__( 'Comics', 'jetpack' ),
221 'singular_name' => esc_html__( 'Comic', 'jetpack' ),
222 'menu_name' => esc_html__( 'Comics', 'jetpack' ),
223 'all_items' => esc_html__( 'All Comics', 'jetpack' ),
224 'add_new' => esc_html__( 'Add New', 'jetpack' ),
225 'add_new_item' => esc_html__( 'Add New Comic', 'jetpack' ),
226 'edit_item' => esc_html__( 'Edit Comic', 'jetpack' ),
227 'new_item' => esc_html__( 'New Comic', 'jetpack' ),
228 'view_item' => esc_html__( 'View Comic', 'jetpack' ),
229 'search_items' => esc_html__( 'Search Comics', 'jetpack' ),
230 'not_found' => esc_html__( 'No Comics found', 'jetpack' ),
231 'not_found_in_trash' => esc_html__( 'No Comics found in Trash', 'jetpack' ),
232 'filter_items_list' => esc_html__( 'Filter comics list', 'jetpack' ),
233 'items_list_navigation' => esc_html__( 'Comics list navigation', 'jetpack' ),
234 'items_list' => esc_html__( 'Comics list', 'jetpack' ),
235 ),
236 'supports' => array(
237 'title',
238 'editor',
239 'thumbnail',
240 'comments',
241 'revisions',
242 'publicize', // Jetpack
243 'subscriptions', // wpcom
244 'shortlinks', // Jetpack
245 ),
246 'rewrite' => array(
247 'slug' => 'comic',
248 'with_front' => false,
249 ),
250 'taxonomies' => array(
251 'category',
252 'post_tag',
253 ),
254 // Only make the type public for sites that support Comics.
255 'public' => true,
256 'menu_position' => 5, // below Posts
257 'map_meta_cap' => true,
258 'has_archive' => true,
259 'query_var' => 'comic',
260 'show_in_rest' => true,
261 ) );
262 }
263
264 public function manage_posts_columns( $columns ) {
265 $new_columns = array(
266 'preview-jetpack-comic' => __( 'Preview', 'jetpack' ),
267 );
268 return array_merge( array_slice( $columns, 0, 2 ), $new_columns, array_slice( $columns, 2 ) );
269 }
270
271 public function manage_posts_custom_column( $column_name, $post_ID ) {
272 if ( 'preview-jetpack-comic' == $column_name && has_post_thumbnail( $post_ID ) ) {
273 echo get_the_post_thumbnail( $post_ID, 'jetpack-comic-thumb' );
274 }
275 }
276
277 /**
278 * The function url_to_postid() doesn't handle pretty permalinks
279 * for CPTs very well. When we're generating an RSS feed to be consumed
280 * for Feedbag (the Reader's feed storage mechanism), eschew
281 * a pretty URL for one that will get the post into the Reader.
282 *
283 * @see http://core.trac.wordpress.org/ticket/19744
284 * @param string $permalink The existing (possibly pretty) permalink.
285 */
286 public function custom_permalink_for_feedbag( $permalink ) {
287 global $post;
288
289 if ( ! empty( $GLOBALS['is_feedbag_rss_script'] ) && self::POST_TYPE == $post->post_type ) {
290 $permalink = home_url( add_query_arg( array( 'p' => $post->ID, 'post_type' => self::POST_TYPE ), '?' ) );
291 }
292
293 return $permalink;
294 }
295
296 /*
297 * Update messages for the Comic admin.
298 */
299 function updated_messages( $messages ) {
300 global $post;
301
302 $messages['jetpack-comic'] = array(
303 0 => '', // Unused. Messages start at index 1.
304 1 => sprintf( __( 'Comic updated. <a href="%s">View comic</a>', 'jetpack'), esc_url( get_permalink( $post->ID ) ) ),
305 2 => esc_html__( 'Custom field updated.', 'jetpack' ),
306 3 => esc_html__( 'Custom field deleted.', 'jetpack' ),
307 4 => esc_html__( 'Comic updated.', 'jetpack' ),
308 /* translators: %s: date and time of the revision */
309 5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Comic restored to revision from %s', 'jetpack'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
310 6 => sprintf( __( 'Comic published. <a href="%s">View comic</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
311 7 => esc_html__( 'Comic saved.', 'jetpack' ),
312 8 => sprintf( __( 'Comic submitted. <a target="_blank" href="%s">Preview comic</a>', 'jetpack'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
313 9 => sprintf( __( 'Comic scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview comic</a>', 'jetpack' ),
314 // translators: Publish box date format, see http://php.net/date
315 date_i18n( __( 'M j, Y @ G:i', 'jetpack' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
316 10 => sprintf( __( 'Comic draft updated. <a target="_blank" href="%s">Preview comic</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
317 );
318
319 return $messages;
320 }
321
322 /**
323 * Should this Custom Post Type be made available?
324 */
325 public function site_supports_comics() {
326 /**
327 * @todo: Extract this out into a wpcom only file.
328 */
329 if ( 'blog-rss.php' == substr( $_SERVER['PHP_SELF'], -12 ) && count( $_SERVER['argv'] ) > 1 ) {
330 // blog-rss.php isn't run in the context of the target blog when the init action fires,
331 // so check manually whether the target blog supports comics.
332 switch_to_blog( $_SERVER['argv'][1] );
333 // The add_theme_support( 'jetpack-comic' ) won't fire on switch_to_blog, so check for Panel manually.
334 $supports_comics = ( ( function_exists( 'site_vertical' ) && 'comics' == site_vertical() )
335 || current_theme_supports( self::POST_TYPE )
336 || get_stylesheet() == 'pub/panel' );
337 restore_current_blog();
338
339 /** This action is documented in modules/custom-post-types/nova.php */
340 return (bool) apply_filters( 'jetpack_enable_cpt', $supports_comics, self::POST_TYPE );
341 }
342
343 $supports_comics = false;
344
345 /**
346 * If we're on WordPress.com, and it has the menu site vertical.
347 * @todo: Extract this out into a wpcom only file.
348 */
349 if ( function_exists( 'site_vertical' ) && 'comics' == site_vertical() ) {
350 $supports_comics = true;
351 }
352
353 /**
354 * Else, if the current theme requests it.
355 */
356 if ( current_theme_supports( self::POST_TYPE ) ) {
357 $supports_comics = true;
358 }
359
360 /**
361 * Filter it in case something else knows better.
362 */
363 /** This action is documented in modules/custom-post-types/nova.php */
364 return (bool) apply_filters( 'jetpack_enable_cpt', $supports_comics, self::POST_TYPE );
365 }
366
367 /**
368 * Anywhere that a feed is displaying posts, show comics too.
369 *
370 * @param WP_Query $query
371 */
372 public function include_in_feeds( $query ) {
373 if ( ! $query->is_feed() )
374 return;
375
376 // Don't modify the query if the post type isn't public.
377 if ( ! get_post_type_object( 'jetpack-comic' )->public )
378 return;
379
380 $query_post_types = $query->get( 'post_type' );
381
382 if ( empty( $query_post_types ) )
383 $query_post_types = 'post';
384
385 if ( ! is_array( $query_post_types ) )
386 $query_post_types = array( $query_post_types );
387
388 if ( in_array( 'post', $query_post_types ) ) {
389 $query_post_types[] = self::POST_TYPE;
390 $query->set( 'post_type', $query_post_types );
391 }
392 }
393
394 /**
395 * API endpoint for front-end image uploading.
396 */
397 public function upload() {
398 global $content_width;
399
400 header( 'Content-Type: application/json' );
401
402 if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'jetpack_comic_upload_nonce' ) )
403 die( json_encode( array( 'error' => __( 'Invalid or expired nonce.', 'jetpack' ) ) ) );
404
405 $_POST['action'] = 'wp_handle_upload';
406
407 $image_id_arr = array();
408 $image_error_arr = array();
409
410 $i = 0;
411
412 while ( isset( $_FILES['image_' . $i ] ) ) {
413 // Create attachment for the image.
414 $image_id = media_handle_upload( "image_$i", 0 );
415
416 if ( is_wp_error( $image_id ) ) {
417 $error = array( $image_id, $image_id->get_error_message() );
418 array_push( $image_error_arr, $error );
419 } else {
420 array_push( $image_id_arr, $image_id );
421 }
422
423 $i++;
424 }
425
426 if ( count( $image_id_arr ) == 0 ) {
427 // All image uploads failed.
428 $rv = array( 'error' => '' );
429
430 foreach ( $image_error_arr as $error )
431 $rv['error'] .= $error[1] . "\n";
432 }
433 else {
434 if ( count( $image_id_arr ) == 1 ) {
435 $image_id = $image_id_arr[0];
436
437 // Get the image
438 $image_src = get_the_guid( $image_id );
439 $image_dims = wp_get_attachment_image_src( $image_id, 'full' );
440
441 // Take off 10px of width to account for padding and border. @todo make this smarter.
442 if ( $content_width )
443 $image_width = $content_width - 10;
444 else
445 $image_width = $image_dims[1] - 10;
446
447 $post_content = '<a href="' . esc_attr( $image_src ) .'"><img src="' . esc_attr( $image_src ) . '?w=' . esc_attr( $image_width ) . '" alt="' . esc_attr( $_FILES['image_0']['name'] ) . '" class="size-full wp-image alignnone" id="i-' . esc_attr( $image_id ) . '" data-filename="' . esc_attr( $_FILES['image_0']['name'] ) . '" /></a>';
448 }
449 else {
450 $post_content = '[gallery ids="' . esc_attr( implode( ',', $image_id_arr ) ) . '"]';
451 }
452
453 // Create a new post with the image(s)
454 $post_id = wp_insert_post( array(
455 'post_content' => $post_content,
456 'post_type' => 'jetpack-comic',
457 'post_status' => 'draft',
458 ),
459 true
460 );
461
462 if ( is_wp_error( $post_id, 'WP_Error' ) ) {
463 // Failed to create the post.
464 $rv = array( 'error' => $post_id->get_error_message() );
465
466 // Delete the uploaded images.
467 foreach ( $image_id_arr as $image_id ) {
468 wp_delete_post( $image_id, true );
469 }
470 }
471 else {
472 foreach ( $image_id_arr as $image_id ) {
473 wp_update_post( array(
474 'ID' => $image_id,
475 'post_parent' => $post_id
476 ) );
477 }
478
479 if ( current_theme_supports( 'post-thumbnails' ) && count( $image_id_arr ) == 1 )
480 set_post_thumbnail( $post_id, $image_id_arr[0] );
481
482 $rv = array( 'url' => add_query_arg( array( 'post' => $post_id, 'action' => 'edit' ), admin_url( 'post.php' ) ) );
483 }
484 }
485
486 die( json_encode( $rv ) );
487 }
488
489 public function add_posts_to_loop( $query ) {
490 // Add comic posts to the tag and category pages.
491 if ( ! is_admin() && $query->is_main_query() && ( $query->is_category() || $query->is_tag() ) ) {
492 $post_types = $query->get( 'post_type' );
493
494 if ( ! $post_types || 'post' == $post_types )
495 $post_types = array( 'post', self::POST_TYPE );
496 else if ( is_array( $post_types ) )
497 $post_types[] = self::POST_TYPE;
498
499 $query->set( 'post_type', $post_types );
500 }
501
502 return $query;
503 }
504
505 /**
506 * Add to REST API post type whitelist
507 */
508 public function allow_rest_api_type( $post_types ) {
509 $post_types[] = self::POST_TYPE;
510 return $post_types;
511 }
512
513 }
514
515 add_action( 'init', array( 'Jetpack_Comic', 'init' ) );
516
517
518 function comics_welcome_email( $welcome_email, $blog_id, $user_id, $password, $title, $meta ) {
519 if ( ( isset( $meta['vertical'] ) && 'comics' == $meta['vertical'] ) || has_blog_sticker( 'vertical-comics', $blog_id ) ) {
520 return __( "Welcome! Ready to publish your first strip?
521
522 Your webcomic's new site is ready to go. Get started by <a href=\"BLOG_URLwp-admin/customize.php#title\">setting your comic's title and tagline</a> so your readers know what it's all about.
523
524 Looking for more help with setting up your site? Check out the WordPress.com <a href=\"http://learn.wordpress.com/\" target=\"_blank\">beginner's tutorial</a> and the <a href=\"http://en.support.wordpress.com/comics/\" target=\"_blank\">guide to comics on WordPress.com</a>. Dive right in by <a href=\"BLOG_URLwp-admin/customize.php#title\">publishing your first strip!</a>
525
526 Lots of laughs,
527 The WordPress.com Team", 'jetpack' );
528 }
529
530 return $welcome_email;
531 }
532
533 add_filter( 'update_welcome_email_pre_replacement', 'comics_welcome_email', 10, 6 );
534