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 😀
Screenshots:
Plugin page:

New/Edit post page:
View Single Post:
RSS:
Code:
Here is the code of this plugins… Hahaha.. little bit messy
<?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 {
/**
* @see Walker::$tree_type
* @since 2.1.0
* @var string
*/
var $tree_type = 'post';
/**
* @see Walker::$db_fields
* @since 2.1.0
* @todo Decouple this
* @var array
*/
var $db_fields = array ('parent' => 'post_parent', 'id' => 'ID');
/**
* @see Walker::start_el()
* @since 2.1.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $page Page data object.
* @param int $depth Depth of page in reference to parent pages. Used for padding.
* @param array $args Uses 'selected' argument for selected page to set selected HTML attribute for option element.
*/
function start_el(&$output, $page, $depth, $args) {
$pad = str_repeat(' ', $depth * 3);
$output .= "\t<option class=\"level-$depth\" value=\"$page->ID\"";
if ( $page->ID == $args['selected'] )
$output .= ' selected="selected"';
$output .= '>';
$title = esc_html($page->post_title);
$output .= "$pad$title";
$output .= "</option>\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,
'cat' => ''
);
$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 name=\"$name\" id=\"$name\">\n";
if ( $show_option_no_change )
$output .= "\t<option value=\"-1\">$show_option_no_change</option>";
if ( $show_option_none )
$output .= "\t<option value=\"" . esc_attr($option_none_value) . "\">$show_option_none</option>\n";
$output .= walk_post_dropdown_tree($pages, $depth, $r);
$output .= "</select>\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 type="hidden" name="myplugin_noncename" id="myplugin_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />'; ?>
<h5><?php _e('Parent') ?></h5>
<p><label for="post_parent">Please select the parent of this post</label></p>
<?php
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'));
}
/* 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;
}
function filtercontentprior(){
$all_plugins = get_plugins();
foreach ( (array)$all_plugins as $plugin_file => $plugin_data) {
//Translate, Apply Markup, Sanitize HTML
$plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true);
$all_plugins[ $plugin_file ] = $plugin_data;
//Filter into individual sections
if ( is_plugin_active($plugin_file) ) {
$active_plugins[ $plugin_file ] = $plugin_data;
}
}
$total_active_plugins = count($active_plugins);
return $total_active_plugins+1;
}
add_filter('posts_where','where_no_parent');
add_filter('the_content','subpost_template', 0, 2 );
add_action('wp_print_scripts', 'disable_autosave');
function disable_autosave() {
wp_deregister_script('autosave');
}
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></p>';
$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;
}
?>
Revision by polvocdo subpost_template()
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;
}
WP Dropdown Post
wp_dropdown_posts()
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'));
Warning
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()
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></p>';
$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;
}
Finally you can see the demo here
This sub post was added on: Tuesday, 09th February, 2010Yesterday, 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():D
Thanks and sorry to polvocdo :) , actually your revision is the answer. Ha ha I’m forget to replace mine with your revision :hammer: ….
This sub post was added on: Friday, 29th January, 2010 EditThis 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)
Image on a sub-post
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.
Uploaded to WordPress.org
This Word Replacer Plugin just approved and uploaded to WordPress Plugins Directory
Please see it in action, here.. http://wordpress.org/extend/plugins/word-replacer/
Note: This post was posted by WP Sub Post Plugin
Image on a sub-post
Komentar (52)
Arsip Statis