WordPress Plugin WP Sub Post
WP Sub Post is a wordpress plugin that allow you to make your wordpress post has a parent or child post.
Notes:
- Child post is a real post that has a parent.
- Child post only displayed on it’s parent post page or when parent page is displayed.
- Child post can not be viewed individually.
- Child post has all possibility like a normal post, such as attachment, custom fields etc.
Features:
- Add/edit parent post directly from your post area.
- No need to edit theme file.
Limitations:
- No setting page
- I don’t know about it’s compatibility.
Bugs:
- Not compatible with my syntax highlight plugin

Screenshot
Plugin page:
New/Edit post page:
View Single Post:
RSS:
Code:
Here is the code of this plugins… Hahaha.. little bit messy
WP Sub Post
WP Sub Post
[raw]<pre><?php
/*
Plugin Name: WP Sub Post
Plugin URI: http://wordpress.org/#
Description: You can make a post is a child of another post.
Author: Takien
Version: 0.1 Alpha
Author URI: http://takien.com
*/
////////////////////////////
class Walker_PostDropdown extends Walker {
var $tree_type = 'post';
var $db_fields = array ('parent' => 'post_parent', 'id' => 'ID');
function start_el(&$output, $page, $depth, $args) {
$pad = str_repeat(' ', $depth * 3);
$output .= "\tID\"";
if ( $page->ID == $args['selected'] )
$output .= ' selected="selected"';
$output .= '>';
$title = esc_html($page->post_title);
$output .= "$pad$title";
$output .= "\n";
}
}
/////////////
function &wp_get_posts($args = '') {
global $wpdb;
$defaults = array(
'child_of' => 0, 'sort_order' => 'ASC',
'sort_column' => 'post_title', 'hierarchical' => 1,
'exclude' => '', 'include' => '',
'meta_key' => '', 'meta_value' => '',
'authors' => '', 'parent' => -1, 'exclude_tree' => '',
'number' => '', 'offset' => 0
);
$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );
$number = (int) $number;
$offset = (int) $offset;
$cache = array();
$key = md5( serialize( compact(array_keys($defaults)) ) );
if ( $cache = wp_cache_get( 'wp_get_posts', 'posts' ) ) {
if ( is_array($cache) && isset( $cache[ $key ] ) ) {
$pages = apply_filters('wp_get_posts', $cache[ $key ], $r );
return $pages;
}
}
if ( !is_array($cache) )
$cache = array();
$inclusions = '';
if ( !empty($include) ) {
$child_of = 0; //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
$parent = -1;
$exclude = '';
$meta_key = '';
$meta_value = '';
$hierarchical = false;
$incpages = preg_split('/[\s,]+/',$include);
if ( count($incpages) ) {
foreach ( $incpages as $incpage ) {
if (empty($inclusions))
$inclusions = $wpdb->prepare(' AND ( ID = %d ', $incpage);
else
$inclusions .= $wpdb->prepare(' OR ID = %d ', $incpage);
}
}
}
if (!empty($inclusions))
$inclusions .= ')';
$exclusions = '';
if ( !empty($exclude) ) {
$expages = preg_split('/[\s,]+/',$exclude);
if ( count($expages) ) {
foreach ( $expages as $expage ) {
if (empty($exclusions))
$exclusions = $wpdb->prepare(' AND ( ID <> %d ', $expage);
else
$exclusions .= $wpdb->prepare(' AND ID <> %d ', $expage);
}
}
}
if (!empty($exclusions))
$exclusions .= ')';
$author_query = '';
if (!empty($authors)) {
$post_authors = preg_split('/[\s,]+/',$authors);
if ( count($post_authors) ) {
foreach ( $post_authors as $post_author ) {
//Do we have an author id or an author login?
if ( 0 == intval($post_author) ) {
$post_author = get_userdatabylogin($post_author);
if ( empty($post_author) )
continue;
if ( empty($post_author->ID) )
continue;
$post_author = $post_author->ID;
}
if ( '' == $author_query )
$author_query = $wpdb->prepare(' post_author = %d ', $post_author);
else
$author_query .= $wpdb->prepare(' OR post_author = %d ', $post_author);
}
if ( '' != $author_query )
$author_query = " AND ($author_query)";
}
}
$join = '';
$where = "$exclusions $inclusions ";
if ( ! empty( $meta_key ) || ! empty( $meta_value ) ) {
$join = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )";
// meta_key and meta_value might be slashed
$meta_key = stripslashes($meta_key);
$meta_value = stripslashes($meta_value);
if ( ! empty( $meta_key ) )
$where .= $wpdb->prepare(" AND $wpdb->postmeta.meta_key = %s", $meta_key);
if ( ! empty( $meta_value ) )
$where .= $wpdb->prepare(" AND $wpdb->postmeta.meta_value = %s", $meta_value);
}
if ( $parent >= 0 )
$where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
$query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'post' AND post_status = 'publish') $where ";
$query .= $author_query;
$query .= " ORDER BY " . $sort_column . " " . $sort_order ;
if ( !empty($number) )
$query .= ' LIMIT ' . $offset . ',' . $number;
$pages = $wpdb->get_results($query);
if ( empty($pages) ) {
$pages = apply_filters('wp_get_posts', array(), $r);
return $pages;
}
// Sanitize before caching so it'll only get done once
$num_pages = count($pages);
for ($i = 0; $i < $num_pages; $i++) {
$pages[$i] = sanitize_post($pages[$i], 'raw');
}
// Update cache.
update_page_cache($pages);
if ( $child_of || $hierarchical )
$pages = & get_page_children($child_of, $pages);
if ( !empty($exclude_tree) ) {
$exclude = (int) $exclude_tree;
$children = get_page_children($exclude, $pages);
$excludes = array();
foreach ( $children as $child )
$excludes[] = $child->ID;
$excludes[] = $exclude;
$num_pages = count($pages);
for ( $i = 0; $i < $num_pages; $i++ ) {
if ( in_array($pages[$i]->ID, $excludes) )
unset($pages[$i]);
}
}
$cache[ $key ] = $pages;
wp_cache_set( 'wp_get_posts', $cache, 'posts' );
$pages = apply_filters('wp_get_posts', $pages, $r);
return $pages;
}
//////////////
function walk_post_dropdown_tree() {
$args = func_get_args();
if ( empty($args[2]['walker']) ) // the user's options are the third parameter
$walker = new Walker_PostDropdown;
else
$walker = $args[2]['walker'];
return call_user_func_array(array(&$walker, 'walk'), $args);
}
function wp_dropdown_posts($args = '') {
$defaults = array(
'depth' => 0, 'child_of' => 0,
'selected' => 0, 'echo' => 1,
'name' => 'page_id', 'show_option_none' => '', 'show_option_no_change' => '',
'option_none_value' => ''
);
$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );
$pages = wp_get_posts($r);
$output = '';
$name = esc_attr($name);
if ( ! empty($pages) ) {
$output = "
<select id=""$name\"" name="\"$name\"">
<option value="\"-1\"">$show_option_no_change</option>
<option value="\""">$show_option_none</option>
\n";
}
$output = apply_filters('wp_dropdown_pages', $output);
if ( $echo )
echo $output;
return $output;
}
/////////////////////////////
/* Use the admin_menu action to define the custom boxes */
add_action('admin_menu', 'myplugin_add_custom_box');
/* Use the save_post action to do something with the data entered */
add_action('save_post', 'myplugin_save_postdata');
/* Adds a custom section to the "advanced" Post and Page edit screens */
function myplugin_add_custom_box() {
if( function_exists( 'add_meta_box' )) {
add_meta_box( 'myplugin_sectionid', __( 'WP Sub Posts', 'myplugin_textdomain' ), 'myplugin_inner_custom_box', 'post', 'side','high' );
//add_meta_box( $id, $title, $callback, $page, $context, $priority );
add_meta_box( 'myplugin_sectionid', __( 'WP Sub Posts', 'myplugin_textdomain' ), 'myplugin_inner_custom_box', 'page', 'advanced' );
} else {
add_action('dbx_post_advanced', 'myplugin_old_custom_box' );
add_action('dbx_page_advanced', 'myplugin_old_custom_box' );
}
}
function myplugin_inner_custom_box() {
echo '
<style type="text/css">
select#parent_id, select#parent_id option {
width:250px;
}
</style>
';
echo '
<input id="myplugin_noncename" name="myplugin_noncename" type="hidden" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />'; ?>
<h5><?php _e('Parent') ?></h5>
<label for="post_parent">Please select the parent of this post</label>
<?php
$currentid = $_GET['post'];
wp_dropdown_posts(array('exclude_tree' => $currentid,
'selected' => $post->post_parent,
'name' => 'parent_id',
'show_option_none' => __('Main Post (no parent)'),
'sort_column' => 'menu_order, post_title'));
}
/* Prints the edit form for pre-WordPress 2.5 post/page */
function myplugin_old_custom_box() {
echo '
<div class="dbx-b-ox-wrapper">' . "\n";
echo '
<fieldset id="myplugin_fieldsetid" class="dbx-box">' . "\n";
echo '
<div class="dbx-h-andle-wrapper">
<h3 class="dbx-handle">' .
__( 'WP Sub Posts', 'myplugin_textdomain' ) . "</h3>
</div>
";
echo '
<div class="dbx-c-ontent-wrapper">
<div class="dbx-content">';
// output editing form
myplugin_inner_custom_box();
// end wrapper
echo "</div>
</div>
</fieldset>
</div>
\n";
}
/* When the post is saved, saves our custom data */
function myplugin_save_postdata( $post_id ) {
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) )) {
return $post_id;
}
// verify if this is an auto save routine. If it is our form has not been submitted, so we dont want
// to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
// Check permissions
if ( 'page' == $_POST['post_type'] ) {
if ( !current_user_can( 'edit_page', $post_id ) )
return $post_id;
} else {
if ( !current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
// OK, we're authenticated: we need to find and save the data
$mydata = $_POST['parent_id'];
return $mydata;
}
add_filter('posts_where','where_no_parent');
add_filter ('the_content','subpost_template', 1, 2 );
function subpost_template($content) {
if(is_singular) {
remove_filter('posts_where','where_no_parent');
}
echo $content;
$idnya = get_the_ID();
$child = new WP_Query("post_type=post&post_parent=".$idnya."");
while($child->have_posts()) : $child->the_post();
echo '
<blockquote>
';
echo '
<h3>';
the_title();
echo '</h3>
';
$childid = get_the_ID();
the_content();
edit_post_link('Edit','','',$childid);
echo '</blockquote>
';
endwhile;
wp_reset_query();
}
function where_no_parent($where) {
global $wpdb;
$where .= " AND post_parent = 0";
return $where;
}
?>[/raw] subpost_template()
subpost_template()
[raw]</pre>
<pre>function subpost_template($content) {
if(is_singular()) {
remove_filter('posts_where','where_no_parent');
}
$parentID = get_the_ID();
$childposts = get_posts(array(
'post_type' => 'post',
'numberposts' => -1,
'post_status' => 'publish',
'post_parent' => $parentID
));
$subcontent = "";
foreach($childposts as $childpost){
$subcontent .= "
<blockquote>
";
$subcontent .= "
<h3>".$childpost->post_title."</h3>
";
$subcontent .= $childpost->post_content;
$subcontent .= '
<a rel="nofollow" href="'.get_edit_post_link($childpost->ID).'">Edit</a>
';
$subcontent .= "</blockquote>
";
}
$content .= $subcontent;
return $content;
}
</pre>
<p>[/raw] WP Dropdown Post
wp_dropdown_posts()
[raw]</p>
<pre>global $post;
$currentid = $_GET['post'];
wp_dropdown_posts(array('exclude_tree' => $currentid,
'selected' => $post->post_parent,
'name' => 'parent_id',
'show_option_none' => __('Main Post (no parent)'),
'sort_column' => 'menu_order, post_title'));
</pre>
<p>[/raw] If it not working please Click here
This plugin is Alpha version, use it for testing purpose only. Any problem caused by this plugin is not my responsibility.
Demo:
See below:
Code Update WP Sub Post
There are some changes to the WP Sub Post:
- Fixed/Added, now child post can be viewed as a single post, with link to the Parent Post instead of displaying blank post with ‘Post not found’ title.
- Added, CSS class and id to the blockquote of the child post. It would be useful to make a link like http://example.com/parentpost.html#childpostXXX. while XXX is your child post ID.
Two functions that are changed subpost_template() and where_no_parent()
WP Sub Post
[raw]<pre>
function subpost_template($content) {
global $post;
$parentID = get_the_ID();
$childposts = get_posts(array(
'post_type' => 'post',
'numberposts' => -1,
'post_status' => 'publish',
'post_parent' => $parentID
));
$subcontent = "";
foreach($childposts as $childpost){
$subcontent .= "
<blockquote class=\"sub_post\" id=\"subpost_".$childpost->ID."\">";
$subcontent .= "
<h3>".$childpost->post_title."</h3>
";
$subcontent .= $childpost->post_content;
$subcontent .= '
<p class="postmetadata"><small>This sub post was added on: '.date('l, dS F, Y',strtotime($childpost->post_date)).' <a href="'.get_edit_post_link($childpost->ID).'" rel="nofollow">Edit</a></small>
';
$subcontent .= "</blockquote>
";
}
if($post->post_parent !== 0) {
$parent_info = '
<blockquote>This post is a child post of <strong>'.get_the_title($post->post_parent).'</strong>. To view the parent post, please <a href="'.get_permalink($post->post_parent).'">click here.</a></blockquote>
';
$content = $parent_info.$content;
}
$content .= $subcontent;
return $content;
}
function where_no_parent($where) {
global $wpdb;
if(!is_single()) {
$where .= " AND post_parent = 0";
}
else {
$where .= " AND post_type = 'post'";
}
return $where;
}
</pre>
<p>[/raw]
Finally you can see the demo here
Yesterday, I was failed to add a demo directly in this site because of incompatibility with smart tags (all smart tags are not working when WP Sub Post is activated).
The problem comes from my old stupid function
subpost_template():DThanks and sorry to polvocdo
, actually your revision is the answer.
Ha ha I’m forget to replace mine with your revision :hammer: ….
This is a child post
This is an individual post (http://takien.com/536/this-is-a-child-post.php) that attached to the another post ( http://takien.com/550/wordpress-plugin-wp-sub-post.php)
Child post could be useful when you want to add an additional information to the main post, news analysis, or update. Instead of editing the main post, you can now simply Add New post and mark it as child post.
Child post also has it’s own functionality, can handle attachment, displaying image. etc.
But you can’t see this post in the post editing page (wp-admin/edit.php) because of filter in the plugin to prevent child post to be displayed individually in the main page, post listing, feed, etc. Hahaha.. don’t worry, I will fix it soon.
Incoming search terms:
- wp_dropdown_posts
- wordpress sub posts
- wordpress sub post
- sub post wordpress
- changuitos
- wp_dropdown_post
- wordpress subposts
- WP Sub Posts
- wordpress post parent plugin
- sub posts wordpress






Pingback: Nothing found for 593 Uploaded-to-wordpress-org Php
Pingback: Rewriting the WP Sub Posts plugin to allow one custom post type to be a child of another custom post type | SeekPHP.com