<?php
add_action( 'after_setup_theme', array( 'Page_For_Post_Type', 'get_instance' ) );
class Page_For_Post_Type {
protected $excludes = array();
protected $original_slugs = array();
protected static $instance;
public static function get_instance() {
if ( self::$instance === null ) {
self::$instance = new self;
}
return self::$instance;
}
public function __construct() {
add_action( 'admin_init', array( $this, 'admin_init' ) );
add_action( 'registered_post_type', array( $this, 'update_post_type' ), 11, 2 );
add_filter( 'wp_nav_menu_objects', array( $this, 'filter_wp_nav_menu_objects' ), 1, 2 );
add_action( 'customize_register', array( $this, 'action_customize_register' ) );
add_filter( 'display_post_states', array( $this, 'filter_display_post_states' ), 100, 2 );
add_action( 'transition_post_status', array( $this, 'action_transition_post_status' ), 10, 3 );
add_action( 'deleted_post', array( $this, 'action_deleted_post' ), 10 );
}
public function admin_init() {
$cpts = get_post_types( array(), 'objects' );
add_settings_section( 'page_for_post_type', __( 'Overzichtpaginas', 'pfpt' ), '__return_false', 'reading' );
foreach ( $cpts as $cpt ) {
if ( ! $cpt->has_archive ) {
continue;
}
$id = "page_for_{$cpt->name}";
$value = get_option( $id );
register_setting( 'reading', $id, array( $this, 'validate_field' ) );
add_settings_field( $id, $cpt->labels->name, array( $this, 'cpt_field' ), 'reading', 'page_for_post_type', array(
'name' => $id,
'post_type' => $cpt,
'value' => $value
) );
}
}
public function cpt_field( $args ) {
$value = intval( $args['value'] );
$default = $args['post_type']->name;
if ( isset( $this->original_slugs[ $args['post_type']->name ] ) ) {
$default = $this->original_slugs[ $args['post_type']->name ];
}
wp_dropdown_pages( array(
'name' => esc_attr( $args['name'] ),
'id' => esc_attr( $args['name'] . '_dropdown' ),
'selected' => $value,
'show_option_none' => sprintf( __( 'Standaard: /%s/' ), $default ),
) );
}
public function action_customize_register( WP_Customize_Manager $wp_customize ) {
$cpts = get_post_types( array(), 'objects' );
$wp_customize->add_section( 'page_for_post_type', array(
'title' => __( 'Overzichtpaginas', 'pfpt' ),
) );
foreach ( $cpts as $cpt ) {
if ( ! $cpt->has_archive ) {
continue;
}
$id = "page_for_{$cpt->name}";
$wp_customize->add_setting( $id, array(
'type' => 'option',
'capability' => 'manage_options',
'default' => 0,
'sanitize_callback' => array( $this, 'validate_field' ),
) );
$wp_customize->add_control( $id, array(
'type' => 'dropdown-pages',
'section' => 'page_for_post_type',
'label' => $cpt->labels->name,
) );
}
}
public function filter_display_post_states( $post_states, $post ) {
$post_type = $post->post_type;
$cpts = get_post_types( array( 'public' => true ), 'objects' );
if ( 'page' === $post_type ) {
if ( in_array( $post->ID, $this->get_page_ids() ) ) {
$cpt = array_search( $post->ID, $this->get_page_ids() );
$post_states["page_for_{$post_type}"] = sprintf( esc_html__( '%1$s overzicht', 'pfpt' ), $cpts[ $cpt ]->labels->name );
}
}
return $post_states;
}
public function validate_field( $new_value ) {
flush_rewrite_rules();
if ( in_array( $new_value, $this->excludes ) ) {
return 0;
}
$this->excludes[] = $new_value;
return intval( $new_value );
}
public function action_transition_post_status( $new_status, $old_status, WP_Post $post ) {
if ( 'publish' !== $new_status ) {
$post_type = array_search( $post->ID, $this->get_page_ids() );
if ( $post_type ) {
delete_option( "page_for_{$post_type}" );
flush_rewrite_rules();
}
}
}
public function action_deleted_post( $post_id ) {
$post_type = array_search( $post_id, $this->get_page_ids() );
if ( $post_type ) {
delete_option( "page_for_{$post_type}" );
flush_rewrite_rules();
}
}
public function update_post_type( $post_type, $args ) {
global $wp_post_types, $wp_rewrite;
$post_type_page = get_option( "page_for_{$post_type}" );
if ( ! $post_type_page ) {
return;
}
if ( 'publish' !== get_post_status( $post_type_page ) ) {
return;
}
$args->rewrite = (array) $args->rewrite;
$old_slug = isset( $args->rewrite['slug'] ) ? $args->rewrite['slug'] : $post_type;
$this->original_slugs[ $post_type ] = $old_slug;
$slug = get_permalink( $post_type_page );
$slug = str_replace( home_url(), '', $slug );
$slug = trim( $slug, '/' );
$args->rewrite = wp_parse_args( array( 'slug' => $slug ), $args->rewrite );
$args->has_archive = $slug;
if ( is_admin() || '' != get_option( 'permalink_structure' ) ) {
if ( $args->has_archive ) {
$archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive;
if ( $args->rewrite['with_front'] ) {
$archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug;
} else {
$archive_slug = $wp_rewrite->root . $archive_slug;
}
add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$post_type", 'top' );
if ( $args->rewrite['feeds'] && $wp_rewrite->feeds ) {
$feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
}
if ( $args->rewrite['pages'] ) {
add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$post_type" . '&paged=$matches[1]', 'top' );
}
}
$permastruct_args = $args->rewrite;
$permastruct_args['feed'] = $permastruct_args['feeds'];
if ( isset( $args->rewrite['permastruct'] ) ) {
$permastruct = str_replace( $old_slug, $slug, $args->rewrite['permastruct'] );
} else {
$permastruct = "{$args->rewrite['slug']}/%$post_type%";
}
add_permastruct( $post_type, $permastruct, $permastruct_args );
}
$wp_post_types[ $post_type ] = $args;
}
public function filter_wp_nav_menu_objects( $sorted_items, $args ) {
global $wp_query;
$queried_object = get_queried_object();
if ( ! $queried_object ) {
return $sorted_items;
}
$object_post_type = false;
if ( is_singular() ) {
$object_post_type = $queried_object->post_type;
}
if ( is_post_type_archive() ) {
$object_post_type = $queried_object->name;
}
if ( is_archive() && is_string( $wp_query->get( 'post_type' ) ) ) {
$query_post_type = $wp_query->get( 'post_type' );
$object_post_type = $query_post_type ?: 'post';
}
if ( ! $object_post_type ) {
return $sorted_items;
}
$page_ids = $this->get_page_ids();
if ( ! isset( $page_ids[ $object_post_type ] ) ) {
return $sorted_items;
}
foreach ( $sorted_items as &$item ) {
if ( $item->type === 'post_type' && $item->object === 'page' && intval( $item->object_id ) === intval( $page_ids[ $object_post_type ] ) ) {
if ( is_singular( $object_post_type ) ) {
$item->classes[] = 'current-menu-item-ancestor';
$item->current_item_ancestor = true;
$sorted_items = $this->add_ancestor_class( $item, $sorted_items );
}
if ( is_post_type_archive( $object_post_type ) ) {
$item->classes[] = 'current-menu-item';
$item->current_item = true;
$sorted_items = $this->add_ancestor_class( $item, $sorted_items );
}
if ( is_archive() && $object_post_type === $wp_query->get( 'post_type' ) ) {
$sorted_items = $this->add_ancestor_class( $item, $sorted_items );
}
}
}
return $sorted_items;
}
protected function get_page_ids() {
$page_ids = array();
foreach ( get_post_types( array(), 'objects' ) as $post_type ) {
if ( ! $post_type->has_archive ) {
continue;
}
if ( 'post' === $post_type->name ) {
$page_id = get_option( 'page_for_posts' );
} else {
$page_id = get_option( "page_for_{$post_type->name}" );
}
if ( ! $page_id ) {
continue;
}
$page_ids[ $post_type->name ] = $page_id;
}
return $page_ids;
}
protected function add_ancestor_class( $child, $items ) {
if ( ! intval( $child->menu_item_parent ) ) {
return $items;
}
foreach ( $items as $item ) {
if ( intval( $item->ID ) === intval( $child->menu_item_parent ) ) {
$item->classes[] = 'current-menu-item-ancestor';
$item->current_item_ancestor = true;
if ( intval( $item->menu_item_parent ) ) {
$items = $this->add_ancestor_class( $item, $items );
}
break;
}
}
return $items;
}
}
if ( ! function_exists( 'get_page_for_post_type' ) ) {
function get_page_for_post_type( $post_type = false ) {
if ( ! $post_type && is_post_type_archive() ) {
$post_type = get_queried_object()->name;
}
if ( ! $post_type && is_singular() ) {
$post_type = get_queried_object()->post_type;
}
if ( ! $post_type && in_the_loop() ) {
$post_type = get_post_type();
}
if ( $post_type && in_array( $post_type, get_post_types() ) ) {
return get_option( "page_for_{$post_type}", false );
}
return false;
}
}