/labs

This is a blog by the staff at the web agency Earth People in Stockholm Sweden. Check out our work and get in contact with us here.

Moving WordPress 2.6 posts to a new 3.x installation

2011-07-29 22:05:45

You have an old 2.6 version of WordPress with 2 000+ posts and 100 000+ in total comments. Today you have installed a brand new WordPress 3.x blog and want to import all data from the old blog but it is just too much to export with the built in export function in WP 2.6. In 2.6 there is no filter option as in 3.x so we had to edit the core export.php to split up the export in parts.

The export.php you will find in wp-admin/includes/export.php

Include approved comments only

First we’re going to edit this file so that only approved comment will be exported, no need to keep the spam, right? This might lower the amount of comments to 30-40 000 instead of the 100 000 +. So, around on line 233 you will find

$comments = $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d", $post->ID) );

Copy that line and comment it out. Paste the line above the old and after %d you add

AND comment_approved = '1'

so the finished code will look like

$comments = $wpdb->get_results( $wpdb->prepare("SELECT * FROM  $wpdb->comments WHERE comment_post_ID = %d AND comment_approved =  '1'", $post->ID) );
#$comments = $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d", $post->ID) );

Save the changes and the first part is done.

Split the export into chunks

To split the export we use the LIMIT option in the database request and edit this file after every chunk we export. Let’s dig into the code again.

Around line 24 will you find

$post_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts $where ORDER BY post_date_gmt ASC");

Copy that line and comment it out. Paste the line above the old and after ASC you add

LIMIT 0, 500

so the finished code will look like

$post_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts $where ORDER BY post_date_gmt ASC LIMIT 0, 500");
#$post_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts $where ORDER BY post_date_gmt ASC");

The first value (0) tells where to start and the second (500) how many results to get. With this values the export will take the first 500 blog posts. The 500 value might have to be lower or can be higher, it all depends on how much load your web server can handle. Save your changes and go and run an export. If you get a popup about saving a file, everything works. If not, try to set a lower amount value.

The export option can be find in Design -> Export in WP 2.6

After the first export, we have to change the LIMIT values from 0, 500 to 501, 500 to get the next 500 posts. Repeat this and up the values after every export you do. Don’t forget go name your files with something like part1, part2 and so on.

Make the import

To import your posts and comments you first login to your new 3.x WP. In the Tools section in the menu you have the option “Import”. Go there and choose “WordPress” from the list.

If this is the first time you use this you will get a popup about installing the import plugin, go ahead and do so. After installing it, network activate it and go back to the tools -> import -> wordpress page.

Now you can select a file to import. Click browse and choose the first part of your exported files. Continue with clicking “Upload file and import”.

On the next page you have some options. You can choose to import the posts with the default admin user, create a new user och choose an existing. Also, check the “download and import attachment” to get pictures and other files that in your posts.

Repeat this steps with all your exported xml files from the old blog. Remember to import them in the same order as you exported them!

/ Mattias & Hjalmar

/ Mattias Hedman

Multiple domains on one WP network installation

2011-07-28 16:02:48

Setting up a new WordPress Network is from version 3.0 very simple and done within 5 min. To set this up so you can use multiple domains to your network blogs is no biggie that either. But what if you want to have multiple domains pointed to the main blog/network and not the sub blogs? Not that easy.

Lets start with how we want the url structure:

blog.site.se
blog.site.se/blog1
blog.site.se/blog2
blog.site.dk
blog.site.dk/blog3
blog.site.no
blog.site.no/blog4
blog.anothersite.se
blog.anothersite.se/blog5
blog.yetanothersite.se
blog.yetanothersite.se/blog6

So, how do we manage to get this with just one (1) WordPress Network installation. Problem we thought at first, but after hours of searching, testing domain mapping plugins and asking in forums we found a solution. The plugin Networks for WordPress solved all the problems.

With this plugin you can create several WordPress networks with just one WordPress installation, perfect! :) And it is very easy to install and use. Here are how you proceed.

Point all the domains right

First of we need to point all the domain names we want to use to the same place. This is done with virtual hosts in Apache. I’m using a local installation for this guide

<VirtualHost *:80>
DocumentRoot "/Users/mattias/Sites/Earthpeople/site"
ServerName blog.site.se
ServerAlias blog.site.dk blog.site.no blog.anothersite.se blog.yetanothersite.se
</VirtualHost>

After that is done, restart the Apache server.

Install WordPress and create a WordPress Network

I’m not going to go through this, but here you have a guide for settings up a WP Network.

Setup the Networks for WordPress

First of, install the plugin Networks for WordPress via the Network Admin -> Plugins page. When done you get a new option in the Sites menu named “Networks”. Go there and you will see this page.

Next step is to create all the new networks we need to get all our domains to work.

Network name: The name of the network, can be anything and you can change this at any time.
Domain: Here, put in the domain you want for the network, eg blog.site.dk.
Path: Must be / for this to work
Create a Root site: Leave this checked.
Root site name: This will be the name of you root site, can be anything and you can change this at any time.
New network Preview: Before adding the network, click the “Check Network Settings”, if all checks is green everything is good and you can create the network. If you get a red status here, something is wrong in your Apache vhost settings.

Assigning the blogs

When all the networks we need are created, hover one of the networks in the list and click the “assign sites” link. This will take you to a new page where you select what blog should belong to what network. Repeat this step for all networks and you are almost done.

Get blogs pages and post to work

At first it’s easy to think that this don’t work due to that you can’t access a blogs single posts page or regular pages. You get a 404 page don’t exist error. This is easy fixed. Just go to the dashboard for the blog and update the permalink structure. Yes, this needs to be done on every single blog manually. When done, you have a multiple network site using just one installation of WordPress. This will save you a lot of time and work in the future when managing your network.

Some things to remember thou. Every network has its own dashboard and network admin page so you can have plugins and themes separated from each network. If you want a plugin to be on all networks, install it in the mu-plugins folder.

/ Mattias & Hjalmar

/ Mattias Hedman

WordPress plugin for fetching hashtag images

2011-07-14 00:54:27

Some time ago i made a quick and dirty site for displaying images from a certain Twitter hashtag. Some hours ago i was asked to tweak this into a WordPress plugin, and here we go. This is just tested on my environment, but should be alright on any WordPress 3+ installation on PHP5 with libcurl.

It currently works with twitpic, instagram, yfrog, plixi, flickr. Adding more services is quite easy and can be done on request. URL’s are being curled and cached for 10-12 minutes using the built-in WP_Cache.

The plugin, when enabled, exposes a template tag which you can add to your theme:

<?php
if(function_exists('hashimage')){
 echo '<ul>';
 echo hashimage('hashtag=unicorn&limit=5');
 echo '</ul>';
}
?>

I can’t be bothered add this to the official WordPress repo, but please download it (or fork it!):
https://github.com/EarthPeople/Hashimage-WP

Some notes:
- The Twitter API only returns the latest results when searching on hashtag, so the result set is limited due to this.
- CSS is up to you. Really. I can’t do CSS. It’s magic to me.

/ peder fjällström

html5 validation with(!) facebook opengraph

2010-09-17 22:27:22

html5 is that new, cool(?) technology which you should(?) be using when making new sites. but, being the thorough developer you are – it just eats you up from the inside when your brand new html5 website won’t validate because your client decided to add a facebook like button.

the facebook open graph protocol/namespace/api/whatever which was released in spring 2010 will only validate with an xhtml doctype. if you want to work in a html5 doctype and use opengraph, you need to apply a little bit of server logic. have a look at this, i won’t bother explaining the source code, i think you’ll get it.

<?php
function is_facebook(){
if(!(stristr($_SERVER["HTTP_USER_AGENT"],’facebook’) === FALSE))
return true;
}
}
?><!DOCTYPE html>
<html dir=”ltr” lang=”en-US”<?php if(is_facebook()){echo ‘ xmlns:fb=”http://www.facebook.com/2008/fbml” xmlns:og=”http://opengraphprotocol.org/schema/”‘;}?>>
<head>
<title><?php bloginfo(‘name’); ?></title>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />

<?php if(is_facebook()){?>
<meta property=”og:title” content=”<?php echo $title;?>”/>
<meta property=”og:description” content=”<?php echo $description;?>”/>
<meta property=”og:type” content=”article”/>
<meta property=”og:image” content=”<?=$path_to_page_thumbnail?>”/>
<meta property=”og:url” content=”http://<?php echo $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];?>”/>
<meta property=”og:site_name” content=”<?=$the_name_of_the_site?>”/>
<meta property=”fb:appid” content=”<?=$your_fb_app_id?>”/>
<?php }?>

one thing to have in mind is that page level caching is a no go if you apply this tactic. if your cache is clever, you could possibly make an exception for the facebook user agent, delivering fresh content to facebook on all requests.

oh well, it’s just a thought. let me know if i missed something.

/ peder fjällström

setting up a wp dev environment on a live site

2010-05-07 16:42:04

developing a wordpress site on the domain it eventually will live on has plenty of advantages (and ok, a few obvious disadvantages not covered in this post…). no need to fiddle around in the db looking for hardcoded urls to the development domain name and when it’s time to launch – you don’t need to bother with db export/imports and stuff.

but – how to do this when there’s already an existing site live on this domain? actually it’s accomplished pretty easily.

make a folder on your live site, call it something like “dev”, put this into the index.php file within this folder:

if(isset($_GET["mode"])&&$_GET["mode"]=="dev"){
	setcookie("dev","true", time()+3600*24*7, "/");
	header("Location: /dev");
}else if(isset($_GET["mode"])&&$_GET["mode"]=="live"){
	setcookie("dev", "", time()-1000, "/");
	header("Location: /dev");
}
if(isset($_COOKIE["dev"])){
	echo "DEVELOPMENT MODE IN YOUR BROWSER: ON | SWITCH";
}else{
	echo "DEVELOPMENT MODE IN YOUR BROWSER: OFF | SWITCH";
}

when a user enters /dev on your live site and clicks ON, a cookie will be set. this cookie can then be checked for, and the server can make a decision wether to show the old site or the development site.

next upload wordpress the usual way to the docroot of the site, and install. make sure you don’t overwrite any existing files on the server when uploading.

lastly – let’s make that cookie work for us. open the file wp-blog-header.php, located in the docroot, and replace the contents with this:

if(isset($_COOKIE["dev"])){ # does the user have the dev cookie?
	if ( !isset($wp_did_header) ) {
		$wp_did_header = true;
		require_once( dirname(__FILE__) . '/wp-load.php' );
		wp();
		require_once( ABSPATH . WPINC . '/template-loader.php' );
	}
}else{
	header("Location: currentindex.htm"); # no? then show the current page
}

one word of warning though – do not run wordpress auto update while developing the site this way. doing so will remove the cookie-check in wp-blog-header.php and exposing your development site to the world. should you need to run the automatic update, remember to make the changes to wp-blog-header.php again.

when you’re ready to go live with your shiny new wordpress site – just remove the cookie check from wp-blog-header.php and let the world in. that’s it folks!

/ peder fjällström

simple custom type

2010-03-04 11:48:59

there’s a point in every wp project (almost) where i need something more than just posts and pages. like stores with longlat data, albums from an artist in the sidebar, etc. now, there are a couple of plugins that do this, like pods and flutter, but they both have their downsides (pods is complexity+doesn’t play nice with wpml and flutter is just plain evil).

so i decided to hack something together which would fill my needs. this plugin cannot collide with anything in wp core or any plugin. please use as you see fit.

1. install the plugin
2. configure your first custom type in the customtypes folder inside the plugin. i’ve included an example type called storelocator which you should be able to rework into your own needs

3. if you enable “showhelp” inside your customtype, you will be presented all the code you need to get this into your templates

4. start inserting and editing content in your new content type!

now don’t go hog wild with this plugin. the plugin stores all data in a single table outside your wp installation and uses serialization/regexps to store/get the data. this means that if you have 1 million rows it will take a couple of seconds for the site to render your data. but if you have 1 millions rows you should probably concider using pods instead (no, not flutter).
click here to download the plugin (v.1.0)

/ peder fjällström

applying oop to wordpress themes

2010-03-04 08:05:00

first couple of wordpress themes people hack together are unmaintainable pieces of junk, so was mine (to say the least).

the problem usually lies in the custom functions.php file, in which all things evil mostly takes place. the code in this file is generally just sequentially executed crap which, if you’re lucky, won’t collide with any core wp functionality or the badly written plugins you install.

plus – variables from functions.php can’t be accessed in header/sidebar/footer files unless you declare every single one of these functions as global. which is a pain.

luckily the solution as simple as elegant. wrap your custom functionality in classes! for most themes one class is enough. i won’t go into detail about how oop works in php5, there is plenty of stuff written on that subject already. but here’s how to apply it to theme development!

inside your functions.php, create a new class:

class YourTheme{
	public function __construct(){
		$this->some_variable_youll_need_throughout_the_theme = "random string, could be an array or anything else";
	}
	public function get_some_var(){
		echo $this->some_variable_youll_need_throughout_the_theme;
	}
}
$YourTheme = new YourTheme;

now, inside any theme file you can access this class by adding this to the top of the file:

global $YourTheme;

then, access all methods and variables this way:

$YourTheme->get_some_var();

You can also set variables really simple, just the way you would expect:

$YourTheme->another_var = "h3ll0 w0r1d";

and retrieve it in another theme file:

echo $YourTheme->another_var;

that’s how simple it is. have fun.

/ peder fjällström