Category: wordpress

Limit number of posts an user can create in WordPress admin panel

If you, by any chance, want to limit the number of posts an user can create in your multi author WordPress blog, there is a nice way to do it. Add the following code in your theme’s functions.php file

[sourcecode language=”php”]
add_action("load-post-new.php","limit_user_by_post_count");
function limit_user_by_post_count(){
$user = get_current_user_id();
if (!current_user_can( ‘manage_options’)) {
//not an admin – so impose the limit
$user_post_count = count_user_posts($user);
if($user_post_count>=10)
header("Location: /wp-admin/edit.php");
}
}
[/sourcecode]

In this example, if the user has 10 posts he/she can not create a new post anymore. Every time he clicks on the “New Post” menu, he will be redirected to “All Posts” page. But the “admin” will not be limited at all 🙂

Sweet, eh?

Launching of WPonFIRE, the premier managed WordPress hosting for everyone

wponfire-banner

Today me and my partner Patrick have launched WPonFIRE, our WordPress based startup. If you are struggling with the performance of your wordpress blog, or spending too much because of some vague pageview based pricing model of your current provider – you may want to host with us. We will host your wordpress blog in a managed, fine tuned, Nginx based environment. We will be monitoring for the spikes, and honestly, there will always be someone listening to your emails, chitchats and try our best to satisfy the requirement.

At this moment, our plans are starting at $19/mo and the highest one is $99/mo. And if you choose yearly plans, we will be generous to give you 2 months for free.

WPonFIRE boxes are properly stress tested, because we really want to make sure that you will get premium return for your every penny, and your viewers will never be disappointed. If you want to integrate your blog with CDN, we can help you with that too. And guess what, based on your current setup you may even qualify for a free migration service. And migration services are usually expensive elsewhere, may cost you up to $500!

Anyway, to supercharge your WordPress blog please give us a shot. You will not be disappointed, promise!

problems uploading large files in php5-fpm and nginx – and solution to that

Today I had encountered a strange error while importing a 10MB XML file in a low end vps, where nginx was configured with php5-fpm and was working pretty nicely. But then, whenever I tried to import that file, after 25% upload the connection drops and page goes blank. It was strange and drove me nuts for some time. I definitely re checked my php.ini settings and everything was fine there, upload_max_filesize was set to 20M and post_max_size was set to 32M. So it was good and definitely not causing any problem. Then I was thinking that something was wrong with nginx config, specially because the connection was dropped in the middle. And guess what, I was actually right 🙂

So I edited the nginx.conf file and added the following values. I actually tried with just “client_max_body_size” but it was not the cause alone. So client_body_timeout fixed it together 🙂

[sourcecode language=”shell”]
client_max_body_size 100m;
client_body_timeout 600s;
[/sourcecode]

After restarting nginx, everything went just perfectly 🙂

Caching Ajax requests in WordPress

In modern WordPress themes, theme developers are serving the page requests via ajax. Both paginated blog page and single posts (might be in full or partial) are served. Though WordPress is very fast if properly tuned, but it’s meaningless to pull the same data from WordPress database again and again unless there is any change. Which means, you can safely cache such ajax requests and reduce loads on your database by adding a few lines of extra code in your theme’s functions.php. In this article, we will learn how to take advantage of such caching in WordPress

Step 1: Register Ajax callback for serving paginated blog pages
Here is a typical codeblock that can serve paginated blog pages via ajax. There is no caching yet
[sourcecode language=”php”]
add_action("wp_ajax_blog", "get_blog");
add_action("wp_ajax_nopriv_blog", "get_blog");

function get_blog(){
global $post;
$page = $_REQUEST[‘page’];
if(!$page) $page=1;
$pp = get_option("posts_per_page");
$offset = ($page*1-1)*$pp;
$args = array(
"posts_per_page"=>$pp,
"offset"=>$offset
);
$posts = get_posts($args); //get the posts
foreach($posts as $post){
setup_postdata( $post );
get_template_part("templates/post",get_post_format($post->ID));
}
die();
}
[/sourcecode]

Now if you go to the url “http://your_blog_url/wp-admin/admin-ajax.php?page=1 ” you can see the latest posts, change the page value to 2,3,4 and so on to see previous posts. Each posts in the loop are rendered via get_templates(). Please note how we used the get_post_format() function in the loop to serve different templates based on post formats.

So what is bad in this code? Nothing, yet Everything! If 100 users are visiting your blog and they are visiting blog pages, each and every time these posts are pulled from database. Each and everytime they are pulling the very same data until you had edited any post, or created a new post. So why this extra load should go to DB? lets minimize it 🙂

Step 2: Add caching layer
here is a revised format of the code block above, but now with caching.
[sourcecode language=”php”]
add_action("wp_ajax_blog", "get_blog");
add_action("wp_ajax_nopriv_blog", "get_blog");

function get_blog(){
global $post;
$page = $_REQUEST[‘page’];
if(!$page) $page=1;

/** supply from cache **/
$page_from_cache = get_option( "artpress_page{$page}", 0 );
if($page_from_cache){
die($page_from_cache);
}
/** cache end **/

$pp = get_option("posts_per_page");
$offset = ($page*1-1)*$pp;
$args = array(
"posts_per_page"=>$pp,
"offset"=>$offset

);
$posts = get_posts($args);

ob_start();
foreach($posts as $post){
setup_postdata( $post );
get_template_part("templates/post",get_post_format($post->ID));
}
$new_cache = ob_get_flush();

/** save the cache **/
update_option( "artpress_page{$page}",$new_cache);
/** end cache **/
die($new_cache);
}
[/sourcecode]

In the code above, we first checked the page number. Then, checked in the wordpress options table if there is a cache present with a key named “artpress_page”. Now, for the first time it wont be there. So we just pull the records from the database as usually and then using the output buffering functions we capture the output, instead of pushing instantly to the browser. And then we update the options table with this output. So next time when same page will be requested, database wont be hit. Ok, database will be hit (this options table data is coming from the db) but you can see it wont touch the posts table again, and avoid running expensive queries (which includes many joins) in that table. It also saves CPU a bit.

Step 3: Invalidate cache whenever a post is edited, or created
This is an important step. We need to flush the cache whenever a new post or page is created to make sure our blog shows the up to date data.

[sourcecode language=”php”]
add_action("save_post","invalidate_cache");
function invalidate_cache(){
$counts = wp_count_posts();
$total_published_posts = $counts->publish;
$posts_per_page = get_option( "posts_per_page");
$total_page = ceil($total_published_posts/$posts_per_page);
for($i=1;$i<=$total_page;$i++){
delete_option( "artpress_page{$i}" );
}
}
[/sourcecode]

Now, we are in good shape. Our ajax requests are served from cache and properly purges whenever necessary. You can serve your single post same way.

If you want to serve single posts from the cache, one thing you need to keep in mind is that you are loading up an important table “options” with a lot of data. So you can change the code above and store the cache in filesystem instead of options table. You should have write permission in the uploads directory by default. So that wont be tough at all.

I hope you enjoyed this article 🙂

Displaying comments template when serving a single post via ajax in wordpress

I ran into this issue this morning, the comment form wasn’t showing up. I was using a custom comment template and I thought that there might be some issue with the custom template. So I tried with default template but the result was same. After googling for a while, I’ve found the workaround. Here is the solution for you

[sourcecode language=”php”]
//functions.php
add_action("wp_ajax_single", "get_single");
add_action("wp_ajax_nopriv_single", "get_single");

function get_single(){
error_reporting(0); //see later to understand why it is here
global $post;
$post_id = $_REQUEST[‘id’];
if($post_id){
$post = get_post( $post_id);
setup_postdata( $post );
get_template_part( "templates/single");
die();
}
}
[/sourcecode]

The code above registers an ajax callback for accepting GET/POST calls at “/wp-admin/admin-ajax.php?action=single&id=” and display the single post using the template file located at “templates/single.php” in your current theme.

Now, in the “templates/single.php” you must include the following code-block at the top to make sure the comments_template() function work

[sourcecode language=”php”]
global $withcomments;
$withcomments = true;
[/sourcecode]

Anyway, it was also mentioned in the codex like this, but I was confused as I thought it was actually inside the “single display” at first 🙂

Loads the comment template. For use in single Post and Page displays. Will not work outside of single displays unless $withcomments is set to 1.

By the way, that error_reporting(0) line is there to suppress a deprecated notice which says that your theme is missing “comments.php” even if it’s there.

Hope you enjoy this article

Saving a HUGE bandwidth cost in WordPress by automatically serving media contents from copy.com

shutterstock_132384233
The title almost says it all. Our mission is to save the bandwidth cost (and ensure better deliverability) by leveraging the power of headless installation of copy.com client in Linux, and then integrating it into WordPress. The integration must work seamlessly so that the viewers don’t see a difference, and at the same time you don’t have to put any extra effort. Beside saving bandwidth, this also reduces extra load from your web server. There’s another surprise which I will tell you later. For now, keep reading 🙂

You need at least a VPS to make this setup working, preferably with root access. These days VPSes are cheap. You can purchase an 128MB VPS for ~14/yr from Ramnode (such a fantastic provider) or may be for ~19/yr from WeLoveServers. Or feel free to use your existing VPSes if you have one.

Step 1: Headless installation of copy.com app
You can use your existing copy.com or register a new one using my referral code http://copy.com?r=Tbcrni, you and I both will be getting an extra 5GB if you do so.

Now log into your linux box via SSH, you need to have root privilege to complete this step.
(more…)

Get Robo for Free – Onepage Application Landing Template for WordPress

Robo is a  small onepage template which is perfect to design a landing page, coming soon or even a small site. Though it’s one page, Robo includes custom post types like sliders, team members, features and google maps. You can showcase your work nicely with Robo.

robo

Robo for WordPress comes with beautiful documentation and includes all the necessary plugins with it, so that you don’t have to worry to leverage all the functionalities provided. Feel free to use Robo in your commercial or personal projects, no link bank is necessary at all.

Source Code: http://bit.ly/RoboWPGithub
Full Documentation is Available at: http://bit.ly/14x7UVZ
View Live at : http://bit.ly/RoboWPLive

Infinite scrolling in WordPress themes

Github Repo: https://github.com/hasinhayder/infinte-scroll-wp

The purpose of infinite scrolling is that you don’t have to navigate through old and new posts by reloading the page each times with them. Rather, old posts will load automatically in the bottom as you scroll down.

Challenges

  1. Event listener for scrolling
  2. Making an Ajax call to load more posts
  3. In the backend, keep track of offsets and deliver posts prior to it
  4. Discard repeated calls with same parameters to avoid redundant data lading

Event Listener

With jQuery it’s pretty easy to create an event listener which listens to window or any dom element’s scrolling. In the listener routine, you need to check whether they user has scrolled to the bottom, and that is done little differently for window object and DOM elements.

For Window Scrolling

$(document).ready(function(){
    $(window).bind('scroll',checkScroll);
});

var checkScroll = function (e){
if($(window).scrollTop() + $(window).height() +20 > $(document).height()) {
    //user scrolled to the bottom
    //now load more contents
}

For DOM elements

$(document).ready(function(){
    $(".selector").bind('scroll',checkScroll);
});

var checkScroll = function (e){
var elem = $(e.currentTarget);
if (elem[0].scrollHeight - elem.scrollTop() -elem.outerHeight()<20)
    //user scrolled to the bottom of this DOM element
    //now load more contents
}

Making an Ajax Call to load the contents

This is divided in two parts. One, in the WordPress functions file which creates an actio hook and listens for incoming Ajax requests and then serve the data and second, from the javascript to make a HTTP POST Ajax call.

In WordPress

<?php
function load_more(){
    $offset = $_POST['offset'];
    $number_of_posts = get_option( "posts_per_page");
    $args = array("posts_per_page"=>$number_of_posts,"offset"=>$offset);
    $posts = get_posts($args);
    foreach($posts as $post){
        setup_postdata( $post );
        global $post;
        ?>
        <div>
            <div><?php the_title();?></div>
            <div><?php the_excerpt();?></div>
        </div>
        <?
    }
    die();
}

add_action("wp_ajax_nopriv_load_more","load_more");
add_action("wp_ajax_load_more","load_more");
?>

WordPress get_posts() takes many parameters, but for our task we need to pass only two and leave other’s with default values. In those two variables, offset is an important one. It is not an id of any post, rather it’s the value from where we want to start loading the previous posts. So for example, if there are 10 posts displayed in our homepage, the offset will be 10, because we want to load previous posts before these tenth post.

One more important thing to note here, and that is how we populated the value of posts_per_page. We used get_option() API to retrieve the actual value of posts per page set by the blog admin from Settings->Reading section of the WordPress admin panel.

The reason for setting th same action hook callbak for both wp_ajax_no_priv and wp_ajax is to make sure that it works for both admin (logged in) and general viewers (non logged in)

In javascript

var post_offset, increment,loading=0;
(function($){
    $(document).ready(function(){
        $(window).bind('scroll',checkScroll);
    });

    var checkScroll = function (e){
        var elem = $(e.currentTarget);
        if($(window).scrollTop() + $(window).height() +20 > $(document).height()) {
            if(loading) return true;
            if(!loading) {
                loading=1;
                var params = {"offset":post_offset,"action":"load_more"}
                $.post("/wp-admin/admin-ajax.php",params,function(data){
                    if(data){
                        post_offset+=increment;
                        loading=0;
                        $(".posts").append(data);

                    }

                });
        //now load more content
    }
}
}
}(jQuery));

Few things to note here. The endpoint URL is one of them. Whenever you are implementing Ajax with WordPress, “/wp-admin/admin-ajax.php” and the use of action variable as “load_more”. Remember that we had create our action hooks with this “load_more” action value (wp_ajax_nopriv_**load_more**).

add_action("wp_ajax_nopriv_load_more","load_more");
add_action("wp_ajax_load_more","load_more");

In our javascript routine, we also checked the value of loading variable hich is false by default, but set as true immediately during an Ajax call is in place and remains true until that Ajax call is finished. This helps to prevent successive call to the Ajax endpoint even before until previous calls are completed.

One more thing to note and that is how we had increase the value of post_offset variable by increment value. Both of them are populated in the index.php and contains the same vaue of WordPress option valueposts_per_page

That’s it, mainly 🙂 Fork the repo at https://github.com/hasinhayder/infinte-scroll-wp and check the sourcecode for even better understanding. Have fun

Shameless Plug

Check out our “Mailbox” WordPress theme which comes with a decent and fancy mailbox UI and has this infinite scrolling feature implemented at it’s best. Purchase today for $15
Mailbox Theme

WordPress 3.5 Bangla Book

This Book will be written by some Good People in a Collaborative Effort.

Idea and work-flow

We will write a good book on wordpress together, in Bangla, to help the developers and enthusiasts start their journey in developing beautiful themes, plugins and applications completely using wordpress

To keep the flow and tone of writing equally pleasing through out the book, we will have audio files narated by one person. These audio files will be distrbuted in smaller chunks – for example each sections will have their own audio file grouped together as a chapter. Once these audio files are available to everyone, the contributors will download and compose in native bangla text.

Afer the text files are written in bangla, a group of developers will add the example source code through out the chapters.

Bundling

After the source code are attached and embedded in each chapter, we will send these files to proof readers. After correction, spell checking and fixing minor faults, these files will be sent for page layout.

The page layout group will generate the final pdf files for each of these chapters. After preparing the pdf files for all these chapters, we will bundle them together as a digital book.

Distribution

The bundled digital book will be distributed under CC-BY-NC-ND (Creative Commons Attribution, Non Commercial, No Derivative) License to make it available for free for everyone.

How to "JAILBREAK" your wordpress.com blog

Wait a minute, “Jailbreak”? for wordpress.com blog? You gotta be kidding me!

Unfortunately that word goes best with your iOS devices. No one jailbreaks anything else. So pardon me for using this word to grab your attention. Back to the article, tell me what will you do in following cases

  • You want to deliver your regular wordpress.com blog from your own domain
  • You have a great blog you maintain in wordpress but you also want to deliver the contents from a subdomain of your choice
  • You want to use Facebook comments instead of wordpress’s own commenting system

The answer of #1 comes at a price of $25 (min). The answer of #2 is still possible by paying $13 and #3 is not possible at all as long your blog is hosted with wordpress.com.

Moreover you certainly be missing few jQuery tweaks all over your site which you could do with your hosted wordpress blog. But wordpress.com is awesome, scalable and you don’t want to host your blog with pesky/cheap hosts.

For this purpose, use wordpress-com-proxy script which is a small script runs in your hosting and deliver your wordpress.com blog from this domain. The masking and rerouting is very good so that your visitors will not be annoyed. Moreover you will have the Facebook comment plugin enabled by default to increase the engagement.

Using this script is very very easy. Follow the instructions available at https://github.com/hasinhayder/wordpress-com-proxy. All you have to to do is check out the script, modify two lines in config.php and upload somewhere (we suggest using a PaaS like AppFog or OpenShift or PagodaBox for hosting because they are just great!)

For a running example, See my actual blog at http://hasin.wordpress.com which is proxied from http://wpproxy.rs.af.cm for demonstration purpose.

wordpress-com-proxy also loads jQuery in the context so that you can now give your blog awesome look and perform amazing things as long as it is possible with jQuery. Check out the script from https://github.com/hasinhayder/wordpress-com-proxy and Enjoy your jailbroken wordpress blog

Shameless Plug

We develop beautiful Admin Panel templates for the web application developers. Our recent product is “Bolt” which is responsive and built on top of Twitter’s bootstrap. Give it a try and let us know how do you like it.

Bolt Responsive Admin Panel Template for Developers
Bolt Responsive Admin Panel Template for Developers