Jetpack_Comic

The Jetpack by WordPress.com Jetpack Comic class.

Defined (1)

The class is defined in the following location(s).

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