Custom Posttype Inheritance (and url structure)

Here we go:

  1. Register your two CPT (= custom post types) e.g. artist, song
  2. Edit the rewrite slug from your child CPT to parent-type/%parent-slug%/child-slug (Attention: Don’t use the same word for parent-type and parent-slug; parent-slug should match your parent CPT slug)
  3. Add a meta box to your child CPT, where you can define a parent CPT
  4. Modify the child CPT permalink to your needs

I wrapped it all up, ready to use:

class myArtistSongs{

    function init_post_types() {
        $args = array(
            'menu_position' => 8,
            'labels' => array(
                'name' => __('Songs', 'myArtistSongs'),
                'all_items' => __('All Songs', 'myArtistSongs'),
                'singular_name' => __('Song', 'myArtistSongs')
            ),
            'menu_icon' => 'dashicons-format-audio',
            'public' => true,
            'publicly_queryable' => true,
            'query_var' => false,
            'capability_type' => 'post',
            'has_archive' => false,
            'rewrite' => array(
                'slug' => 'artist/%artist%/songs',
                'feeds' => true,
                'pages' => true,
                'with_front' => true,
            ),
            'taxonomies' => array(
                'artist'
            ),
            'supports' => array(
                'title',
                'editor',
                'thumbnail',
                'excerpt'
            )
        );
        register_post_type( 'song', $args);
        $args = array(
            'menu_position' => 8,
            'labels' => array(
                'name' => __('Artists', 'myArtistSongs'),
                'all_items' => __('All Artists', 'myArtistSongs'),
                'singular_name' => __('Artist', 'myArtistSongs')
            ),
            'menu_icon' => 'dashicons-groups',
            'public' => true,
            'publicly_queryable' => true,
            'query_var' => false,
            'capability_type' => 'post',
            'has_archive' => false,
            'rewrite' => array(
                'slug' => 'artists',
                'feeds' => true,
                'pages' => true,
                'with_front' => true,
            ),
            'taxonomies' => array(
                'artist'
            ),
            'supports' => array(
                'title',
                'editor',
                'thumbnail',
                'excerpt'
            )
        );
        register_post_type( 'artist', $args);
    }

    static function song_permalink($permalink, $post_id, $leavename) {
        if (strpos($permalink, '%artist%') === FALSE) return $permalink;
        $post = get_post($post_id);
        if (!$post) return $permalink;
        $artist = get_post_meta($post->ID, '_artist', true);
        if ($artist > 0) {
            $artist = get_post($artist);
            if (!$artist) $artist = false;
            else $artist = $artist->post_name;
        }
        if (!$artist) $artist="no-artist";
        return str_replace('%artist%', $artist, $permalink);
    }

    function add_meta_box() {
        add_meta_box(
            'article-parent',
            __('Artist',''),
            array('myArtistSongs', 'meta_box'),
            'song',
            'side',
            'low'
        );
    }

    function meta_box($post) {
        $artist = get_post_meta($post->ID, '_artist', true);
        global $wp_query, $post;
        $old_wp_query = $wp_query;
        $old_post = $post;
        $loop = new WP_Query(array('post_type' => 'artist', 'posts_per_page=-1'));
        echo "<select name="artist" id='artist'>";
        $no_value = __('(no artist)','myArtistSongs');
        echo "<option value=""".(empty($artist)?" selected='selected'":'').">".$no_value."</option>";
        if($loop->have_posts()) while ($loop->have_posts()) {
            $loop->the_post();
            $o_id = get_the_ID();
            $o = get_the_title();
            echo "<option value="{$o_id}"".(!empty($artist) && $artist == $o_id?" selected='selected'":'').">{$o}</option>";
        }
        echo "</select>";
        $post = $old_post;
        $wp_query = $old_wp_query;
    }

    function save($post_id) {
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
            return;
        if ( !current_user_can( 'edit_post', $post_id ) )
            return;
        if ($_POST['artist']) {
            update_post_meta($post_id, '_artist', $_POST['artist']);
        } else {
            delete_post_meta($post_id, '_artist');
        }
    }
}

add_action('init', array('myArtistSongs', 'init_post_types'));
add_filter('post_link',  array('myArtistSongs', 'song_permalink'), 10, 3);
add_filter('post_type_link',  array('myArtistSongs', 'song_permalink'), 10, 3);
add_action('add_meta_boxes', array('myArtistSongs', 'add_meta_box'));
add_action( 'save_post', array('myArtistSongs','save') );

Leave a Comment