Multiple WordPress installation sharing one user table

Recently my project required me to setup multiple WordPress installation and each WordPress installation does different thing. The only problem that i faced was to have a synchronize login between these three WordPress installation. Short to say, once a user has logged into the system, they will not have to do it again if they decide to proceed to the next WordPress installation.  There are a few great explanation on how this can be done even on WordPress forum. However, it seems like everyone faced a little problem of having to touch the core of WordPress in order for their user to access another WordPress installation without getting the message 'You do not have sufficient permissions to access this page.'.

Requirement

Before i began, you will need to know certain things in order for WordPress to share user table across multiple WordPress installation.

  • All your WordPress installation must be within the same database
  • Each WordPress installation must have different prefix ( or else you are performing overwriting)
  • URL must be within the domain. Multiple domain will have problem authenticating an already logged in user although sharing user table is still possible.
  • WordPress installation version must be similar across the media you wished to share.

Enough of my crap. Let's start with something simple.

Sharing WordPress user table

Our objective here is to share WordPress table across sub domain. Although different domain will also work but your user will have to log in manually on each different domain WordPress installation. (i will explain later) The main thing you will need for each sub domain to use a single user table is to point all your WordPress installation towards one user table. In order to do that, you will have to edit your wp-config.php file on all your sub domain WordPress installation and place the following code into it.

define('CUSTOM_USER_TABLE', 'wp_users');
define('CUSTOM_USER_META_TABLE', 'wp_usermeta');

where wp_ is your WordPress installation prefix, change it to your own prefix. The above constant variable (or code) is telling your WordPress installation that we won't be needing any users and usermeta table. We will be using the one defined above. Hence, any user who login from different installation will all see the same table. (sharing user has accomplished)

Login once only

Pointing everyone to one table is pretty simple. Next we want our user only login once and every time when they visit a new WordPress installation blog. In this case, we will have to further add in some code into ALL wp-config.php file. (although you don't need all but let's play safe)

Dump the following code into all of your wp-config.php file (including the main and sub installation).

$baseurl = 'http://www.domain.com'; // replace with the actual domain name for your root site
$cookiehash = md5($baseurl);
define('COOKIEHASH', $cookiehash);
define ('AUTH_COOKIE', 'wordpress_'.COOKIEHASH);
define ('SECURE_AUTH_COOKIE', 'wordpress_sec_'.COOKIEHASH);
define ('LOGGED_IN_COOKIE','wordpress_logged_in_'.COOKIEHASH);
define ('TEST_COOKIE', 'wordpress_test_cookie');

define('COOKIE_DOMAIN', '.domain.com'); // change domain with your root site
define('COOKIEPATH', '/');

 define('AUTH_KEY',        'to be generated at https://api.wordpress.org/secret-key/1.1/');
 define('SECURE_AUTH_KEY','to be generated at https://api.wordpress.org/secret-key/1.1/');
 define('LOGGED_IN_KEY',  'to be generated at https://api.wordpress.org/secret-key/1.1/');
 define('NONCE_KEY',       'to be generated at https://api.wordpress.org/secret-key/1.1/');

 define('AUTH_SALT',   'can use one of the key on https://api.wordpress.org/secret-key/1.1/');
 define('LOGGED_IN_SALT',       'can use one of the key on  https://api.wordpress.org/secret-key/1.1/');

The above will be adviced to be placed on all of your WordPress installation that you wished to have an one time login feature. Please take note if there is a constant variable or code similar on your wp-config.php file, please remove them. The objective of having the above code similar across each WordPress installation is so that each installation can authenticate your user login detail correctly across different installation.

Now, take note of the cookie constant variable. WordPress uses that to authenticate your user login and cookie authentication cannot do cross domain validation. And this is the reason why different domain couldn't achieve one time login feature.

Explanation on what's going on

I tried very hard to explain in least technical aspect as possible but i still thinks it is quite technical so allow me to summarize a bit here.

  • Firstly we point all WordPress installation to the main WordPress installation user table where all user login details are located.
  • Secondly, we copy the required code for one time login to all WordPress installation including the main WordPress installation in order for all WordPress installation to proceed the same way to identify a user (it's like everyone holding the same key to open one lock where the lock refer to the user)
  • Thirdly, 'You do not have sufficient permissions to access this page.' message bugs you. (it's a good thing)

Alright, this should be it.

Solve the problem of You do not have sufficient permissions to access this page

Soon, you figure when you try to login from other WordPress installation using other WordPress installation user detail, you receive the message  'You do not have sufficient permissions to access this page.'. If you manage to get this message after you have logged in to the main blog and directly access your sub ones. This means that one time login has successfully implemented. The reason why this is happening is because within WordPress core code, it is checking your user capability with the prefix that you have install on that WordPress installation and not the one used on our user table.

Example, main blog A uses prefix wp_ and sub blog B uses prefix wpp_. You tried to login from blog B and you get the error message because on blog B installation, it is checking wpp_ instead of wp_ .

This logic resist within the core code on wp-include/capabilities.php and you will have to dig into the core in order to fix this problem or manually add the record yourself every time a new user register.

If you select the first option to manually insert the record on other sub domain, you will go to your usermeta table and insert the following record.

wp-multiple-installation-one-user

Or you may want to change the logic in your core implementation so that all your sub domain knows the correct usermeta table to look into. If you do, change all sub domain WordPress installation capabilities.php file located at wp-include/capabilities.php line 514 where you will see this.

	function _init_caps() {
		global $wpdb;
		$this->cap_key = $wpdb->prefix . 'capabilities';
		$this->caps = &$this->{$this->cap_key};
		if ( ! is_array( $this->caps ) )
			$this->caps = array();
		$this->get_role_caps();
	}

On the comment above you will notice the trouble maker. Now, hardcode the prefix to the main domain to this instead for all your sub domain. (because everyone is sharing the same user table, we won't have the detail of their unique prefix + user_roles table.)

//$this->cap_key = $wpdb->prefix . 'capabilities'; //this is the trouble maker
$this->cap_key = 'wp_capabilities'; //this is the trouble maker

this will do the trick but you will have to change this every time wordpress update 🙁

I have another personal solution which doesn't need to do both or required to set a default permission type for all user who do not have access across sub domain. However, there is a problem with it that is why i can't release it at the moment (although it's really a small problem) but let me fix it and release for you guys in the near future 🙂

Security

Having the same user to access across different WordPress installation is great but doing this might degrade the strength of each WordPress installation. The security concern lays on the one time login implementation and not how each WordPress installation is using the same user table. Since one time login required every security measurement to be same across different WordPress installation, this means that only one installation is required to be broken in order to access all other sub domain. Short to say, instead of multiple wall of defends for each implementation. Now, we have just one.

**** UPDATE *****

Unfortunately, the above method doesn't work anymore for latest WordPress version (hence, stop your research and keep reading the same appraoch). In order to get auto login in multiple wordpress sub domain sites with multiple installation, another approach has to be done. It is still possible to get all users to login automatically across every website and sharing user login without using CUSTOM_USER_TABLE. It is more reliable and you do not have to combine databases together. However, this approach require a bit of bypassing and modification certain behavior which i will try to write one out if i get the time. Do dig deep into the core code to understand what you guys might think as an 'easy' approach might not be that easy anymore.

Sorting post according to post tag in WordPress

It's been quite a while since i write new post on Hungred Dot Com as i got stuck with my Malay language examination (sigh..) and other project that i'm working on. And recently i was trying to sort one of my WordPress theme according to its post tag and found that there is no easy way to sort your post tag in prioritize or customization ways. Although i manage to make it work on the WordPress theme. It still required additional query to the database although i tried to minimized it. Well, i guess you will have to pay the price for things that WordPress doesn't support i guess. Nonetheless, this is the optimized version of how i get it done on my WordPress theme.

Getting Started

Before i start, let me explain what i am sorting here. Basically, i have only two post tag which are 'sold out' and 'available' and i'm sorting it according to this sequence.

  1. Sticky post
  2. Available tag
  3. Sold out tag
  4. Others

The objective is pretty simple but working on the code require a bit more work than i though. Let's see how do i simplify the explanation so that all of us can understand. I'll just split them in 4 section as shown on my sorting sequence. Let's pray that we all get it. (hahaha..)

Sorting sticky post

The starting sort which is also the one who will initialize all variables (so that we don't enquire the database twice) is located on the first sorting sequence.

<?php
global $wp_query;
$tmp = $wp_query->query;	// backup the original query
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;	//determine the current page number
$sticky = get_option('sticky_posts');	//get all sticky post from db
$num2display = get_option('posts_per_page');	//get post per page from db
$numHadDisplay = 0;		//display post counter
$maxnumofpost = 0;		//maximum post counter
$args = array(
	'post__in'  => $sticky, // we only want to see sticky post
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => $paged,
	'showposts' => ($num2display),
	'offset' => (($paged-1)*$num2display)	//we need to tell our query the offset so that it will display correctly on subsequence page
);
 query_posts(array_merge($args,$wp_query->query));	//merge my query with the original one (don't have to do this, its up to you)
 $numHadDisplay += $wp_query->post_count;	//increment the post that has displayed
 $maxnumofpost += $wp_query->found_posts;	//increment the maximum post on this section

I have commented above so that you guys can figure out what the heck am i doing. I'm basically initializing all the things i need on the top to avoid redundant call to the database. Once you have finish this, the next bit of code is to print them out on the screen. This bits of code are the same for all print out after the logic has been applied.

	<?php if (have_posts()) : ?>
		<?php while (have_posts()) : the_post(); ?>
			<div class="post" id="post-<?php the_ID(); ?>">
				<div class="commentP">
					<div class="commentC">
					<?php comments_popup_link('0', '1', '%'); ?>
					</div>
				</div>

				<h2 class="home_title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<p class="byline"><small>
					by <?php the_author() ?>, 				<?php the_time('F jS') ?> • 				<?php the_category(' •  ') ?> • 				<?php edit_post_link('Edit', '', '  •  '); ?>
				</small></p>
				<div class="entry">
					<?php the_content('<div id="moretag">MORE »</div>');?>
				</div>
				<p class="tags"><?php the_tags('Item Status: ', ', ', '<br />'); ?></p>
			</div>
		<?php endwhile; ?>
	<?php endif; ?>

It's just a loop to print out everything. It should be different from your theme. (looping should be the same though)

Sorting available post tag

NOW, i'm hoping that the first sorting part doesn't confuse you. If it does, then you should stop reading and start thinking of your own logic. But it should be alright for most of you. The next page should get a bit more challenging.

<?php
if($numHadDisplay < $num2display){	//check whether the previous tag post has enough to print (too little, we will need to help to fill up the gap
if($maxnumofpost%$num2display == 0)	//we will need to have decimal to determine the correct page
$maxnumofpost++;
$maxpage = ceil($maxnumofpost/$num2display);	//find the maximum page the previous tag post sections can get
$offset = 0;
if(($paged-$maxpage) == 0)			//although we are at n page where n can be any number, this section might just run the first time. Hence, first page.
$offset = 0;
else if($paged >= 1)		//subsequence page we will calculate the number of post we have printed to fill up the grap on the previous page PLUS the number that had already display to get the starting index
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

$args = array(
	'tag'=> "available",
	'post__not_in'  => $sticky,
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),	// this is the starting page (we do not follow the current page because each section start page is different)
	'showposts' => ($num2display - $numHadDisplay),	//show this amount of post
	'caller_get_posts'=>1,	//do not show any sticky post
	'offset' => $offset		//get the record after this offset
);
 query_posts($args);
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>

The above is pretty confusing but this is all the logic we need for all subsequence section. In here, you must understand that we are trying to prioritize each tag to display first. Hence, each level in your priority list will initialize at different time. Therefore, we need to calculate what is the starting offset of that part, number of post to display and the correct page to display at that time.

After the above logic has been applied, you will perform another print out on the screen as shown previously.

Sorting sold out post tag

Like i mention on the previous section. That is all the logic we need. Hence, the code for this section differ only at the query level.

<?php
if($numHadDisplay < $num2display){
if($maxnumofpost%$num2display == 0)
$maxnumofpost++;
$maxpage = ceil($maxnumofpost/$num2display);
global $wp_query;
$offset = 0;
if(($paged-$maxpage) == 0)
$offset = 0;
else if($paged >= 1)
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

$args = array(
	'tag'=> "sold-out", // it's sold out instead
	'post__not_in'  => $sticky,
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),
	'showposts' => ($num2display - $numHadDisplay),
	'caller_get_posts'=>1,
	'offset' => $offset
);
 query_posts($args);
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>

Then, we will just output all the things out as usual as shown on the sticky section.

Sorting other post

Once, we display all the tag we want, other not so important post will be thrown at the back.

<?php
if($numHadDisplay < $num2display){
if($maxnumofpost%$num2display == 0)
$maxnumofpost++;
global $wp_query;
$maxpage = ceil($maxnumofpost/$num2display);
$soldout = get_term_by('slug','sold-out','post_tag');
$available = get_term_by('slug','available','post_tag');
$offset = 0;
if(($paged-$maxpage) == 0)
$offset = 0;
else if($paged >= 1)
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

// echo "max page = ". $maxpage . "<br/>";
// echo "previous printed = " . ($num2display-($maxnumofpost)%$num2display) . "<br/>";
// echo "added to printed = ". ((($paged-$maxpage) -1 )*$num2display) . "<br/>";
// echo "max num of post = ".$maxnumofpost . "<br/>";
// echo "page = ". ($paged-$maxpage) . "<br/>";
// echo "offset = ". ($offset) . "<br/>";
// echo "showposts = ".  ($num2display - $numHadDisplay) . "<br/>";

$args = array(
	'post__not_in'  => $sticky, // do not display sticky post
	'tag__not_in'=> array($available->term_id, $soldout->term_id), // do not display sold out and available tag post
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),
	'showposts' => ($num2display - $numHadDisplay),
	'caller_get_posts'=>1,
	'offset' => $offset
);
 query_posts(array_merge($args));
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>

As usual, print them out once the above has initialize.

Fix pagination

Once you have done all that, you will notice that your WordPress theme page is wrong as it takes the last query total page. Hence, you will need to call the backup query that we did previous to display the proper maximum page our site have.

<?php  query_posts($tmp); ?>

That's it!

Full Sorting code

In case you can't follow without the full code. Here is the one i have 🙂

<?php get_header(); ?>
<!-- start #content -->
<div id="page">
	<div id="content">
<?php
global $wp_query;
$tmp = $wp_query->query;	// backup the original query
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;	//determine the current page number
$sticky = get_option('sticky_posts');	//get all sticky post from db
$num2display = get_option('posts_per_page');	//get post per page from db
$numHadDisplay = 0;		//display post counter
$maxnumofpost = 0;		//maximum post counter
$args = array(
	'post__in'  => $sticky,
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => $paged,
	'showposts' => ($num2display),
	'offset' => (($paged-1)*$num2display)	//start query
);
 query_posts(array_merge($args,$wp_query->query));	//merge my query with the original one (don't have to do this, its up to you)
 $numHadDisplay += $wp_query->post_count;	//increment the post that has displayed
 $maxnumofpost += $wp_query->found_posts;	//increment the maximum post on this section
?>
	<?php if (have_posts()) : ?>
		<?php while (have_posts()) : the_post(); ?>
			<div class="post" id="post-<?php the_ID(); ?>">
				<div class="commentP">
					<div class="commentC">
					<?php comments_popup_link('0', '1', '%'); ?>
					</div>
				</div>

				<h2 class="home_title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<p class="byline"><small>
					by <?php the_author() ?>, 				<?php the_time('F jS') ?> • 				<?php the_category(' •  ') ?> • 				<?php edit_post_link('Edit', '', '  •  '); ?>
				</small></p>
				<div class="entry">
					<?php the_content('<div id="moretag">MORE »</div>');?>
				</div>
				<p class="tags"><?php the_tags('Item Status: ', ', ', '<br />'); ?></p>
			</div>
		<?php endwhile; ?>
	<?php endif; ?>
<?php
if($numHadDisplay < $num2display){	//check whether the previous tag post has enough to print (too little, we will need to help to fill up the gap
if($maxnumofpost%$num2display == 0)	//we will need to have decimal to determine the correct page
$maxnumofpost++;
$maxpage = ceil($maxnumofpost/$num2display);	//find the maximum page the previous tag post sections can get
$offset = 0;
if(($paged-$maxpage) == 0)			//although we are at n page where n can be any number, this section might just run the first time. Hence, first page.
$offset = 0;
else if($paged >= 1)		//subsequence page we will calculate the number of post we have printed to fill up the grap on the previous page PLUS the number that had already display to get the starting index
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

$args = array(
	'tag'=> "available",
	'post__not_in'  => $sticky,
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),	// this is the starting page (we do not follow the current page because each section start page is different)
	'showposts' => ($num2display - $numHadDisplay),	//show this amount of post
	'caller_get_posts'=>1,	//do not show any sticky post
	'offset' => $offset		//get the record after this offset
);
 query_posts($args);
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>
	<?php if (have_posts()) : ?>
		<?php while (have_posts()) : the_post(); ?>
			<div class="post" id="post-<?php the_ID(); ?>">
				<div class="commentP">
					<div class="commentC">
					<?php comments_popup_link('0', '1', '%'); ?>
					</div>
				</div>

				<h2 class="home_title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<p class="byline"><small>
					by <?php the_author() ?>, 				<?php the_time('F jS') ?> • 				<?php the_category(' •  ') ?> • 				<?php edit_post_link('Edit', '', '  •  '); ?>
				</small></p>
				<div class="entry">
					<?php the_content('<div id="moretag">MORE »</div>');?>
				</div>
				<p class="tags"><?php the_tags('Item Status: ', ', ', '<br />'); ?></p>
			</div>
		<?php endwhile; ?>
	<?php endif; ?>
<?php
}
if($numHadDisplay < $num2display){
if($maxnumofpost%$num2display == 0)
$maxnumofpost++;
$maxpage = ceil($maxnumofpost/$num2display);
global $wp_query;
$offset = 0;
if(($paged-$maxpage) == 0)
$offset = 0;
else if($paged >= 1)
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

$args = array(
	'tag'=> "sold-out",
	'post__not_in'  => $sticky,
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),
	'showposts' => ($num2display - $numHadDisplay),
	'caller_get_posts'=>1,
	'offset' => $offset
);
 query_posts($args);
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>
	<?php if (have_posts()) : ?>
		<?php while (have_posts()) : the_post(); ?>
			<div class="post" id="post-<?php the_ID(); ?>">
				<div class="commentP">
					<div class="commentC">
					<?php comments_popup_link('0', '1', '%'); ?>
					</div>
				</div>

				<h2 class="home_title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<p class="byline"><small>
					by <?php the_author() ?>, 				<?php the_time('F jS') ?> • 				<?php the_category(' •  ') ?> • 				<?php edit_post_link('Edit', '', '  •  '); ?>
				</small></p>
				<div class="entry">
					<?php the_content('<div id="moretag">MORE »</div>');?>
				</div>
				<p class="tags"><?php the_tags('Item Status: ', ', ', '<br />'); ?></p>
			</div>
		<?php endwhile; ?>
	<?php endif; ?>
<?php
}
if($numHadDisplay < $num2display){
if($maxnumofpost%$num2display == 0)
$maxnumofpost++;
global $wp_query;
$maxpage = ceil($maxnumofpost/$num2display);
$soldout = get_term_by('slug','sold-out','post_tag');
$available = get_term_by('slug','available','post_tag');
$offset = 0;
if(($paged-$maxpage) == 0)
$offset = 0;
else if($paged >= 1)
$offset = ($num2display-($maxnumofpost)%$num2display) + ((($paged-$maxpage) -1 )*$num2display);

// echo "max page = ". $maxpage . "<br/>";
// echo "previous printed = " . ($num2display-($maxnumofpost)%$num2display) . "<br/>";
// echo "added to printed = ". ((($paged-$maxpage) -1 )*$num2display) . "<br/>";
// echo "max num of post = ".$maxnumofpost . "<br/>";
// echo "page = ". ($paged-$maxpage) . "<br/>";
// echo "offset = ". ($offset) . "<br/>";
// echo "showposts = ".  ($num2display - $numHadDisplay) . "<br/>";

$args = array(
	'post__not_in'  => $sticky,
	'tag__not_in'=> array($available->term_id, $soldout->term_id),
	'orderby'=>'date',
	'order'=>'DESC',
	'paged' => ($paged-$maxpage),
	'showposts' => ($num2display - $numHadDisplay),
	'caller_get_posts'=>1,
	'offset' => $offset
);
 query_posts($args);
 $numHadDisplay += $wp_query->post_count;
 $maxnumofpost += $wp_query->found_posts;
?>
	<?php if (have_posts()) : ?>
		<?php while (have_posts()) : the_post(); ?>
			<div class="post" id="post-<?php the_ID(); ?>">
				<div class="commentP">
					<div class="commentC">
					<?php comments_popup_link('0', '1', '%'); ?>
					</div>
				</div>

				<h2 class="home_title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<p class="byline"><small>
					by <?php the_author() ?>, 				<?php the_time('F jS') ?> • 				<?php the_category(' •  ') ?> • 				<?php edit_post_link('Edit', '', '  •  '); ?>
				</small></p>
				<div class="entry">
					<?php the_content('<div id="moretag">MORE »</div>');?>
				</div>
				<p class="tags"><?php the_tags('Item Status: ', ', ', '<br />'); ?></p>
			</div>
		<?php endwhile; ?>

	<?php else : ?>
		<div class="post">
			<h2 class="center">Not Found</h2>
			<p class="center">Sorry, we can't find the thing you are looking for. Please try to search for it.</p>
		</div>
		<?php include (TEMPLATEPATH . "/searchform.php"); ?>
	<?php endif; ?>
<?php } ?>
<?php  query_posts($tmp); ?>
		<div class="navigation post">
			<div class="alignleft"><?php if(function_exists('wp_pagenavi')) { wp_pagenavi(); } ?>  </div>
		</div>
	</div>
<?php get_sidebar(); ?>
</div>
<!-- end #content -->
<?php get_menu(); ?>
<?php get_footer(); ?>

And if you still not convince that it work, you can have a look at this store.looliwun.com.

Summary

The challenging part on sorting post tag is that you will have to take care of each sequence logic. In this logic that i have, i have only added around 5 WordPress query to get what i want. (let's don't calculate what WordPress did inside, hahaha..) But it depends on what you want, you might try other ways to achieve the same result. Enjoy 🙂

P.S: you can further optimize this by blocking access to each section after there is no post to be displayed for some of the top logic. Example, sticky has 1 post, available have 2 post, sold out have 100 post. In this case, after 2nd page, sticky and available post should have ended but we still enquire the database to check. This can be optimized. 🙂

wp_insert_post went into infinity loop problem or return blank page

If you customize WordPress and used wp_insert_post to insert a post into WordPress manually, you might face a problem like i do. The page will go into infinity loop and you ended up on an empty or blank page instead of returning you to your original page/post.  You will start digging into your own code before looking into code. Finally, you found nothing seems to go wrong with your code and start digging into WordPress code. There, you will find wp_insert_post causing you this problem.

wp_insert_post problem

the problem lies with user capability when one use wp_insert_post to give other user the ability to insert post into WordPress. wp_insert_post uses the method current_user_can to check whether the given user has the capability to publish a post. After that i too have no idea what went wrong. However, this only happen when you set your post_status as publish. If you happen to change publish into other status such as draft, you will find that you can successfully insert your WordPress post without the problem of going into an infinity loop. However, this doesn't happen to every WordPress setup. Apparently my TEST environment doesn't seems to get such behavior compared to my LIVE one. Furthermore, if you dig deeper into WordPress wp_insert_post used methods, you will find that none of them are using any expensive loop or redirect function. Therefore, i suspect one of the method in wp_insert_post is performing a checking with user capability and publish post. a lighten me if you manage to find out what's wrong.

wp_insert_post solution

But i want my user to have the capability of a subscribers but is able to publish a post themselves. If you are like me, you may want to try to bypass the checking on publish post. If you look into the code implementation of wp_insert_post, you will find that most of the checking are looking for the keyword publish. Another alternative to publish your post without using the keyword publish is to use alternative keyword, future. The keyword future allows you to publish your post almost instantly similar to publish but it is a bit slower as the schedule will have to take care of publishing the article of yours. That's it, you shouldn't be getting an infinity loop after using future instead of publish! Good luck!

Tutorial: disable _blank attribute from opening new window

Today is an interesting day. I was working on my project and found that i have a hard time looking for a way to disable my target attribute, _blank, which will open a new window and display the item there.  Surprisingly, i found tons of how to create pop out box and many discussion regarding setting up a window.open instruction. But no one care to explain how to stop or disable it! Hence, i decide to write it out myself.

Pop out box

We all know how to enable a pop out box. We can do that either by window.open or using target attribute _blank to pass the work to another window. We can also do that for form submission but bringing out another box is not very professional unless you are showing certain information. Hence, most of us will go with ajax or iframe way of synchronize submission. Nonetheless, pop out box is a necessity in our web environment. While opening a new window box is easy but how about disabling it?

Disable _blank attribute

Disabling a pop out box or anything that will pop out is pretty simple. If you try to recall how you disable those anchor link, you might have an idea how you are going to disable all other types of link. Most pop out box is being initialize by a click. Hence, the event that we are interested with is onclick event handler. However, different people will have different ways of disabling an anchor link such as

<a href="JavaScript: void();">link</a>

or

<a href="#">link</a>

But we are interested in

<a href="JavaScript: return false;">link</a>

In order to disable pop out, it is the same as how we used to disable link. Hence, if you have a link such as this,

<a href="http://somewhere.com" target="_blank">link</a>

it will bring you to somewhere.com on a new pop out box. And if you want to prevent that, you will do this.

<a href="http://somewhere.com" target="_blank" onclick='return false;'>link</a>

That's it! To prevent window.open, we just remove that sentence! haha..