PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.3.4
Jetpack – WP Security, Backup, Speed, & Growth v7.3.4
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.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Jetpack_Comic {
4 const POST_TYPE = 'jetpack-comic';
5
6 static function init() {
7 static $instance = false;
8
9 if ( ! $instance )
10 $instance = new Jetpack_Comic;
11
12 return $instance;
13 }
14
15 /**
16 * Conditionally hook into WordPress.
17 *
18 * Themes must declare that they support this module by adding
19 * add_theme_support( 'jetpack-comic' ); during after_setup_theme.
20 *
21 * If no theme support is found there is no need to hook into
22 * WordPress. We'll just return early instead.
23 */
24 function __construct() {
25 // Make sure the post types are loaded for imports
26 add_action( 'import_start', array( $this, 'register_post_types' ) );
27
28 // Add to REST API post type whitelist
29 add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_rest_api_type' ) );
30
31 // If called via REST API, we need to register later in lifecycle
32 add_action( 'restapi_theme_init', array( $this, 'maybe_register_post_types' ) );
33
34 // Return early if theme does not support Jetpack Comic.
35 if ( ! ( $this->site_supports_comics() ) )
36 return;
37
38 $this->register_post_types();
39
40 add_action( 'pre_get_posts', array( $this, 'add_posts_to_loop' ) );
41
42 // In order for the Feedbag job to find Comic posts, we need to circumvent any pretty
43 // URLs in the RSS feed given to Feedbag in favor of /?p=123&post_type=jetpack-comic
44 add_filter( 'the_permalink_rss', array( $this, 'custom_permalink_for_feedbag' ) );
45
46 // There are some cases (like when Feedbag is fetching posts) that the comics
47 // post type needs to be registered no matter what, but none of the UI needs to be
48 // available.
49
50 add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
51
52 if ( function_exists( 'queue_publish_post' ) ) {
53 add_action( 'publish_jetpack-comic', 'queue_publish_post', 10, 2 );
54 }
55
56 add_action( 'pre_get_posts', array( $this, 'include_in_feeds' ) );
57
58 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
59
60 add_filter( 'manage_' . self::POST_TYPE . '_posts_columns', array( $this, 'manage_posts_columns' ) );
61 add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', array( $this, 'manage_posts_custom_column' ), 10, 2 );
62 add_image_size( 'jetpack-comic-thumb', 150, 0, false );
63
64 // Enable front-end uploading for users special enough.
65 if ( current_user_can( 'upload_files' ) && current_user_can( 'edit_posts' ) ) {
66 add_action( 'wp_ajax_jetpack_comic_upload', array( $this, 'upload' ) );
67 add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
68 }
69
70 /**
71 * Add a "Convert to Comic" and "Convert to Post" option to the bulk
72 * edit dropdowns.
73 */
74 add_action( 'admin_footer-edit.php', array( $this, 'admin_footer' ) );
75 add_action( 'load-edit.php', array( $this, 'bulk_edit' ) );
76 add_action( 'admin_notices', array( $this, 'bulk_edit_notices' ) );
77
78 }
79
80 public function admin_footer() {
81 $post_type = get_post_type();
82
83 ?>
84 <script type="text/javascript">
85 jQuery( document ).ready( function( $ ) {
86 <?php if ( ! $post_type || 'post' == $post_type ) { ?>
87 $( '<option>' )
88 .val( 'post2comic' )
89 .text( <?php echo json_encode( __( 'Convert to Comic', 'jetpack' ) ); ?> )
90 .appendTo( "select[name='action'], select[name='action2']" );
91 <?php } ?>
92 <?php if ( ! $post_type || self::POST_TYPE == $post_type ) { ?>
93 $( '<option>' )
94 .val( 'comic2post' )
95 .text( <?php echo json_encode( __( 'Convert to Post', 'jetpack' ) ); ?> )
96 .appendTo( "select[name='action'], select[name='action2']" );
97 <?php } ?>
98
99 $( '#message.jetpack-comic-post-type-conversion' ).remove().insertAfter( $( '.wrap h2:first' ) ).show();
100 });
101 </script>
102 <?php
103 }
104
105 /**
106 * Handle the "Convert to [Post|Comic]" bulk action.
107 */
108 public function bulk_edit() {
109 if ( empty( $_REQUEST['post'] ) )
110 return;
111
112 $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
113 $action = $wp_list_table->current_action();
114
115 check_admin_referer( 'bulk-posts' );
116
117 if ( 'post2comic' == $action || 'comic2post' == $action ) {
118 if ( ! current_user_can( 'publish_posts' ) )
119 wp_die( __( 'You are not allowed to make this change.', 'jetpack' ) );
120
121 $post_ids = array_map( 'intval', $_REQUEST['post'] );
122
123 $modified_count = 0;
124
125 foreach ( $post_ids as $post_id ) {
126 $destination_post_type = ( $action == 'post2comic' ) ? self::POST_TYPE : 'post';
127 $origin_post_type = ( $destination_post_type == 'post' ) ? self::POST_TYPE : 'post';
128
129 if ( current_user_can( 'edit_post', $post_id ) ) {
130 $post = get_post( $post_id );
131
132 // Only convert posts that are post => comic or comic => post.
133 // (e.g., Ignore comic => comic, page => post, etc. )
134 if ( $post->post_type != $destination_post_type && $post->post_type == $origin_post_type ) {
135 $post_type_object = get_post_type_object( $destination_post_type );
136
137 if ( current_user_can( $post_type_object->cap->publish_posts ) ) {
138 set_post_type( $post_id, $destination_post_type );
139 $modified_count++;
140 }
141 }
142 }
143 }
144
145 $sendback = remove_query_arg( array( 'exported', 'untrashed', 'deleted', 'ids' ), wp_get_referer() );
146
147 if ( ! $sendback )
148 $sendback = add_query_arg( array( 'post_type', get_post_type() ), admin_url( 'edit.php' ) );
149
150 $pagenum = $wp_list_table->get_pagenum();
151 $sendback = add_query_arg( array( 'paged' => $pagenum, 'post_type_changed' => $modified_count ), $sendback );
152
153 wp_safe_redirect( $sendback );
154 exit();
155 }
156 }
157
158 /**
159 * Show the post conversion success notice.
160 */
161 public function bulk_edit_notices() {
162 global $pagenow;
163
164 if ( 'edit.php' == $pagenow && ! empty( $_GET['post_type_changed'] ) ) {
165 ?><div id="message" class="updated below-h2 jetpack-comic-post-type-conversion" style="display: none;"><p><?php
166 printf( _n( 'Post converted.', '%s posts converted', $_GET['post_type_changed'], 'jetpack' ), number_format_i18n( $_GET['post_type_changed'] ) );
167 ?></p></div><?php
168 }
169 }
170
171 public function register_scripts() {
172 wp_enqueue_style( 'jetpack-comics-style', plugins_url( 'comics/comics.css', __FILE__ ) );
173 wp_style_add_data( 'jetpack-comics-style', 'rtl', 'replace' );
174
175 wp_enqueue_script(
176 'jetpack-comics',
177 Jetpack::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