- Timestamp:
- 07/01/2020 07:42:15 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/handbook/handbook.php
r9845 r9990 3 3 * Plugin Name: Handbook 4 4 * Description: Features for a handbook, complete with glossary and table of contents 5 * Author: Nacin 5 * Author: WordPress.org 6 * Author URI: https://wordpress.org/ 7 * License: GPLv2 or later 8 * Text Domain: wporg 6 9 */ 7 10 8 11 const WPORG_HANDBOOK_PLUGIN_FILE = __FILE__; 9 12 13 require_once __DIR__ . '/inc/init.php'; 14 require_once __DIR__ . '/inc/handbook.php'; 10 15 require_once __DIR__ . '/inc/admin-notices.php'; 11 16 require_once __DIR__ . '/inc/callout-boxes.php'; … … 20 25 require_once __DIR__ . '/inc/blocks.php'; 21 26 22 /**23 * Initialize our handbooks24 *25 */26 class WPorg_Handbook_Init {27 28 public static function get_post_types() {29 return (array) apply_filters( 'handbook_post_types', array( 'handbook' ) );30 }31 32 static function init() {33 34 $post_types = self::get_post_types();35 36 new WPorg_Handbook_TOC( $post_types );37 38 foreach ( $post_types as $type ) {39 new WPorg_Handbook( $type );40 }41 42 WPorg_Handbook_Glossary::init();43 44 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_styles' ) );45 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );46 }47 48 static public function enqueue_styles() {49 wp_enqueue_style( 'wporg-handbook-css', plugins_url( '/stylesheets/callout-boxes.css', __FILE__ ), array(), '20200121' );50 }51 52 static public function enqueue_scripts() {53 wp_enqueue_script( 'wporg-handbook', plugins_url( '/scripts/handbook.js', __FILE__ ), array( 'jquery' ), '20150930' );54 }55 56 }57 58 add_action( 'after_setup_theme', array( 'WPorg_Handbook_Init', 'init' ) );59 60 class WPorg_Handbook {61 62 public $post_type = '';63 public $setting_name = '';64 65 protected $label = '';66 67 static function caps() {68 return array(69 'edit_handbook_pages', 'edit_others_handbook_pages',70 'edit_published_handbook_pages',71 );72 }73 74 static function editor_caps() {75 return array(76 'publish_handbook_pages',77 'delete_handbook_pages', 'delete_others_handbook_pages',78 'delete_published_handbook_pages', 'delete_private_handbook_pages',79 'edit_private_handbook_pages', 'read_private_handbook_pages',80 );81 }82 83 /**84 * Returns the handbook name.85 *86 * If one isn't set via settings, one is generated.87 *88 * @param string $post_type Optional. Handbook post type.89 * @param bool $raw Optional. Return only explicitly set name without attempting to generate default name?90 * @return string91 */92 static function get_name( $post_type = 'handbook', $raw = false ) {93 // Prefer explicitly configured handbook name.94 $name = get_option( $post_type . '_name' );95 96 // If handbook name isn't set, try root relative site path.97 if ( ! $raw && empty( $name ) ) {98 if ( is_multisite() ) {99 $name = trim( get_blog_details()->path, '/' );100 } else {101 $name = trim( parse_url( get_option( 'home' ), PHP_URL_PATH ), '/' );102 }103 104 // If no name defined yet, try handbook post type if not standard.105 if ( empty( $name ) && ( 'handbook' != $post_type ) ) {106 $name = ucfirst( substr( $post_type, 0, -9 ) );107 }108 109 $name .= ' Handbook';110 }111 112 return trim( $name );113 }114 115 function __construct( $type ) {116 if ( 'handbook' != $type ) {117 $this->post_type = $type . '-handbook';118 } else {119 $this->post_type = $type;120 }121 122 $this->label = ucwords( str_replace( array( '-', '_' ), ' ', $this->post_type ) );123 $this->label = apply_filters( 'handbook_label', $this->label, $this->post_type );124 125 $this->setting_name = $this->post_type . '_name';126 127 add_filter( 'user_has_cap', array( $this, 'grant_handbook_caps' ) );128 add_action( 'widgets_init', array( $this, 'register_post_type' ) );129 add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );130 add_action( 'template_redirect', array( $this, 'redirect_handbook_root_page' ) );131 add_filter( 'template_include', array( $this, 'template_include' ) );132 add_filter( 'pre_get_posts', array( $this, 'pre_get_posts' ) );133 add_action( 'widgets_init', array( $this, 'handbook_sidebar' ), 11 ); // After P2134 add_action( 'wporg_email_changes_for_post_types', array( $this, 'wporg_email_changes_for_post_types' ) );135 add_action( 'p2_action_links', array( $this, 'disable_p2_resolved_posts_action_links' ) );136 add_action( 'admin_init', array( $this, 'add_name_setting' ) );137 add_filter( 'body_class', array( $this, 'add_body_class' ) );138 add_filter( 'post_class', array( $this, 'add_post_class' ) );139 add_filter( 'o2_process_the_content', array( $this, 'disable_o2_processing' ) );140 add_filter( 'o2_application_container', array( $this, 'o2_application_container' ) );141 add_filter( 'o2_view_type', array( $this, 'o2_view_type' ) );142 add_filter( 'o2_post_fragment', array( $this, 'o2_post_fragment' ) );143 add_filter( 'comments_open', array( $this, 'comments_open' ), 10, 2 );144 add_filter( 'wp_nav_menu_objects', array( $this, 'highlight_menu_handbook_link' ) );145 add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );146 }147 148 /**149 * Adds 'Handbook Front Page' post state indicator for handbook landing pages.150 *151 * @param string[] $post_states An array of post display states.152 * @param WP_Post $post The current post object.153 * @return string[]154 */155 function display_post_states( $post_states, $post ) {156 if ( $this->post_is_landing_page( $post ) ) {157 $post_states[] = __( 'Handbook Front Page', 'wporg' );158 }159 return $post_states;160 }161 162 /**163 * Adds custom handbook-related classes to body tag.164 *165 * * Adds 'single-handbook' class for any handbook page.166 * * Adds 'handbook-landing-page' class for page acting as a handbook landing167 * page.168 *169 * @param array $classes Array of body classes.170 * @return array171 */172 function add_body_class( $classes ) {173 if ( is_singular() && wporg_is_handbook( $this->post_type ) ) {174 $classes[] = 'single-handbook';175 }176 177 if ( wporg_is_handbook_landing_page() ) {178 $classes[] = 'handbook-landing-page';179 }180 181 return $classes;182 }183 184 /**185 * Adds 'type-handbook' class to the list of post classes to a handbook post186 * when appropriate.187 *188 * @param array $classes Array of post classes.189 * @return array190 */191 function add_post_class( $classes ) {192 if ( $this->post_type === get_post_type() ) {193 $classes[] = 'type-handbook';194 }195 196 return $classes;197 }198 199 function add_name_setting() {200 register_setting( 'general', $this->setting_name, 'esc_attr' );201 202 $label = ( 'handbook' == $this->post_type ) ?203 __( 'Handbook name', 'wporg' ) :204 sprintf( __( 'Handbook name (%s)', 'wporg' ), substr( $this->post_type, 0, -9 ) );205 206 add_settings_field(207 $this->setting_name,208 '<label for="' . esc_attr( $this->setting_name ) . '">' . $label . '</label>',209 array( $this, 'name_setting_html' ),210 'general'211 );212 }213 214 function name_setting_html() {215 $value = get_option( $this->setting_name, '' );216 echo '<input type="text" id="' . esc_attr( $this->setting_name ) . '" name="' . esc_attr( $this->setting_name ) . '" value="' . esc_attr( $value ) . '" class="regular-text ltr" />';217 }218 219 function grant_handbook_caps( $caps ) {220 if ( ! is_user_member_of_blog() ) {221 return $caps;222 }223 224 foreach ( self::caps() as $cap ) {225 $caps[ $cap ] = true;226 }227 228 if ( ! empty( $caps['edit_pages'] ) ) {229 foreach ( self::editor_caps() as $cap ) {230 $caps[ $cap ] = true;231 }232 }233 234 return $caps;235 }236 237 function register_post_type() {238 if ( 'handbook' != $this->post_type ) {239 $slug = substr( $this->post_type, 0, -9 );240 } else {241 $slug = 'handbook';242 }243 244 $default_config = array(245 'labels' => array(246 'name' => $this->label,247 'singular_name' => sprintf( __( '%s Page', 'wporg' ), $this->label ),248 'menu_name' => $this->label,249 'all_items' => sprintf( __( '%s Pages', 'wporg' ), $this->label ),250 ),251 'public' => true,252 'show_ui' => true,253 'show_in_rest' => true,254 'capability_type' => 'handbook_page',255 'map_meta_cap' => true,256 'has_archive' => true,257 'hierarchical' => true,258 'menu_icon' => 'dashicons-book',259 'menu_position' => 11,260 'rewrite' => array(261 'feeds' => false,262 'slug' => $slug,263 'with_front' => false,264 ),265 'delete_with_user' => false,266 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'revisions', 'wpcom-markdown' ),267 );268 // Allow customization of the default post type configuration via filter.269 $config = apply_filters( 'handbook_post_type_defaults', $default_config, $slug );270 271 $this->label = $config['labels']['name'];272 273 register_post_type( $this->post_type, $config );274 }275 276 /**277 * Determines if the given values correspond to a post that acts as the278 * landing page for this handbook.279 *280 * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post.281 * @return bool True if the given information would make such a post the282 * handbook's landing page.283 */284 protected function post_is_landing_page( $post = null ) {285 $is_landing_page = false;286 287 $post_type = get_post_type( $post );288 $slug = get_post_field( 'post_name', $post );289 290 if (291 $post_type === $this->post_type292 &&293 (294 $post_type === $slug295 ||296 $post_type === "{$slug}-handbook"297 ||298 'handbook' === $slug299 ||300 'welcome' === $slug301 )302 &&303 ! wp_get_post_parent_id( $post )304 ) {305 $is_landing_page = true;306 }307 308 return $is_landing_page;309 }310 311 /**312 * For a handbook page acting as the root page for the handbook, change its313 * permalink to be the equivalent of the post type archive link.314 *315 * @param string $post_link The post's permalink.316 * @param WP_Post $post The post in question.317 */318 function post_type_link( $post_link, $post ) {319 $post_type = get_post_type( $post );320 321 // Only change links for this handbook's post type.322 if ( $this->post_is_landing_page( $post ) ) {323 $post_link = get_post_type_archive_link( $post_type );324 }325 326 return $post_link;327 }328 329 /**330 * For a handbook page acting as the root page for the handbook, redirect to the331 * post type archive link for the handbook.332 */333 function redirect_handbook_root_page() {334 global $wp_query;335 336 if ( is_singular( $this->post_type )337 &&338 ! is_preview()339 &&340 ! $wp_query->is_handbook_root341 &&342 $this->post_is_landing_page( get_queried_object_id() )343 ) {344 wp_safe_redirect( get_post_type_archive_link( $this->post_type ), 301 );345 exit;346 }347 }348 349 /**350 * Use 'single-handbook.php' as the fallback template for handbooks.351 *352 * Applies to handbooks using a post type other than 'handbook', as well as353 * the handbook root page.354 *355 * @param string $template The path of the template to include.356 * @return string357 */358 function template_include( $template ) {359 global $wp_query;360 361 // Don't override Embeds362 if ( is_embed() ) {363 return $template;364 }365 366 $handbook_templates = array();367 368 // For singular handbook pages not of the 'handbook' post type.369 if ( is_singular( $this->post_type ) && 'handbook' !== $this->post_type ) {370 $handbook_templates = array( "single-{$this->post_type}.php", 'single-handbook.php' );371 }372 // For handbook landing page.373 elseif ( $wp_query->is_handbook_root && get_query_var( 'handbook' ) === $this->post_type ) {374 if ( 'handbook' !== $this->post_type ) {375 $handbook_templates[] = "single-{$this->post_type}.php";376 }377 $handbook_templates[] = 'single-handbook.php';378 }379 380 if ( $handbook_templates ) {381 if ( $handbook_template = locate_template( $handbook_templates ) ) {382 $template = $handbook_template;383 }384 }385 386 return $template;387 }388 389 function pre_get_posts( $query ) {390 // Bail early if query is not for this handbook's post type.391 if ( get_query_var( 'post_type' ) !== $this->post_type ) {392 // Request is obviously not for a handbook root page. (Though if the request is393 // for some other handbook's root page will be determined by that handbook.)394 if ( empty( get_query_var( 'handbook' ) ) ) {395 $query->is_handbook_root = false;396 }397 return;398 }399 400 $query->is_handbook_root = false;401 402 if ( $query->is_main_query() && ! $query->is_admin && ! $query->is_search && $query->is_post_type_archive( $this->post_type ) ) {403 // If the post type has a page to act as an archive index page, get that.404 $page = get_page_by_path( $this->post_type, OBJECT, $this->post_type );405 if ( ! $page ) {406 $slug = substr( $this->post_type, 0, -9 );407 $page = get_page_by_path( $slug, OBJECT, $this->post_type );408 }409 if ( ! $page ) {410 $page = get_page_by_path( 'handbook', OBJECT, $this->post_type );411 }412 if ( ! $page ) {413 $page = get_page_by_path( 'welcome', OBJECT, $this->post_type );414 }415 if ( $page ) {416 $query->set( 'p', $page->ID );417 $query->is_handbook_root = true;418 419 $query->is_archive = false;420 $query->is_post_type_archive = false;421 $query->is_single = true;422 $query->is_singular = true;423 }424 $query->set( 'handbook', $this->post_type );425 }426 }427 428 function handbook_sidebar() {429 $sidebar_args = array(430 'id' => $this->post_type,431 'name' => sprintf( __( '%s Sidebar', 'wporg' ), $this->label ),432 'description' => sprintf( __( 'Used on %s pages', 'wporg' ), $this->label ),433 'before_widget' => '<aside id="%1$s" class="widget %2$s">',434 'after_widget' => '</aside>',435 'before_title' => '<h2 class="widget-title">',436 'after_title' => '</h2>',437 );438 439 $sidebar_args = apply_filters( 'wporg_handbook_sidebar_args', $sidebar_args, $this );440 441 register_sidebar( $sidebar_args );442 443 require_once __DIR__ . '/inc/widgets.php';444 register_widget( 'WPorg_Handbook_Pages_Widget' );445 }446 447 function wporg_email_changes_for_post_types( $post_types ) {448 if ( ! in_array( $this->post_type, $post_types ) ) {449 $post_types[] = $this->post_type;450 }451 452 return $post_types;453 }454 455 /**456 * Disable the P2 Resolved Posts plugin's action links (e.g. "Flag Unresolved"),457 * if that plugin is active.458 */459 function disable_p2_resolved_posts_action_links() {460 if ( ( $this->post_type == get_post_type() ) && class_exists( 'P2_Resolved_Posts' ) && isset( $GLOBALS['p2_resolved_posts'] ) && is_object( $GLOBALS['p2_resolved_posts'] ) ) {461 remove_filter( 'p2_action_links', array( P2_Resolved_Posts::instance(), 'p2_action_links' ), 100 );462 }463 }464 465 /**466 * Disables handbook post content processing by the o2 plugin.467 *468 * @param bool $process_with_o2 Is o2 about to process the post content?469 * @return bool470 */471 function disable_o2_processing( $process_with_o2 ) {472 return ( is_singular() && $this->post_type === get_post_type() ) ? false : $process_with_o2;473 }474 475 /**476 * Use the correct ID for the content container element.477 *478 * @param string $container The container element ID.479 * @return string480 */481 function o2_application_container( $container ) {482 return ( is_singular() && $this->post_type === get_post_type() ) ? '#primary' : $container;483 }484 485 /**486 * Tell o2 to use the 'single' view type for handbook pages. This removes a lot of the meta487 * cruft around the content.488 *489 * @param string $view_type The o2 view type.490 * @return string491 */492 function o2_view_type( $view_type ) {493 return ( is_singular() && $this->post_type === get_post_type() ) ? 'single' : $view_type;494 }495 496 /**497 * Tell o2 to treat the handbook page the same as it would a normal page.498 *499 * @param array $post_fragment The o2 post fragment500 * @return array501 */502 function o2_post_fragment( $post_fragment ) {503 $post = get_post( $post_fragment['id'] );504 if ( ! $post ) {505 return $post_fragment;506 }507 508 if ( $post->post_type === $this->post_type ) {509 $post_fragment['isPage'] = true;510 }511 512 return $post_fragment;513 }514 515 /**516 * Don't show the comment form on handbook pages.517 *518 * @param bool $open Whether the comments are open or not.519 * @param WP_Post|int $post_id The current post.520 * @return bool521 */522 function comments_open( $open, $post_id ) {523 $post = get_post( $post_id );524 if ( ! $post ) {525 return $open;526 }527 528 if ( $post->post_type === $this->post_type ) {529 return false;530 }531 532 return $open;533 }534 535 /**536 * Highlights a menu link to the handbook home page when on any constituent537 * handbook page.538 *539 * Assuming the handbook page isn't already directly linked in the menu,540 * preference is given to highlight a link to the front page of the current541 * handbook. Barring the presence of such a link, it will check to see if542 * there is a link to a 'handbook' or 'handbooks' page, which could be the543 * case for multi-handbook sites.544 *545 * @param array $menu_items Array of sorted menu items.546 * @return array547 */548 function highlight_menu_handbook_link( $menu_items ) {549 // Must be on a handbook page that isn't the handbook landing page (which will already be handled).550 if ( ! is_page( array( 'handbook', 'handbooks' ) ) && ( ! wporg_is_handbook() || wporg_is_handbook_landing_page() ) ) {551 return $menu_items;552 }553 554 // Menu must not have an item that is already noted as being current.555 $current_menu_item = wp_filter_object_list( $menu_items, array( 'current' => true ) );556 if ( $current_menu_item ) {557 return $menu_items;558 }559 560 // Menu must have an item that links to handbook home page.561 $root_handbook_menu_item = wp_filter_object_list( $menu_items, array( 'url' => wporg_get_current_handbook_home_url() ) );562 if ( ! $root_handbook_menu_item ) {563 // Or it must have an item that links to a 'handbook' or 'handbooks' page.564 $page_slug = is_page( 'handbooks' ) ? 'handbooks' : 'handbook';565 $page = get_page_by_path( $page_slug );566 if ( $page ) {567 $root_handbook_menu_item = wp_filter_object_list( $menu_items, array( 'object_id' => $page->ID ) );568 }569 }570 if ( ! $root_handbook_menu_item ) {571 return $menu_items;572 }573 574 // Add current-menu-item class to the handbook menu item.575 reset( $root_handbook_menu_item );576 $handbook_item_index = key( $root_handbook_menu_item );577 $menu_items[ $handbook_item_index ]->classes[] = 'current-menu-item';578 579 return $menu_items;580 }581 582 }
Note: See TracChangeset
for help on using the changeset viewer.