Y Mouse Axis Off in VirtualBox

Posted July 11th, 2013 (Updated 10 Aug 2014) in Uncategorized

I just installed Ubuntu 13.04 in Virtualbox 4.2.16 and found much to my annoyance that the VM thought my mouse was a little higher than it actually was:

Ubuntu thinks my mouse is a little higher than it actually is

It turns out this is caused by having 3D acceleration turned on in VM Settings – Display window. After doing a bit of sleuthing I came across a forum post on virtualbox.org with a command that did the trick nicely.

Simply open a terminal and run

VBoxManage setextradata global GUI/Customizations noStatusBar

Restart your VM and voila. Perfect mouse working with 3D acceleration!

Mouse Y-Axis working as it should

Read More »

Google Charts ChartRangeFilter Mobile Workaround

Posted June 28th, 2013 (Updated 10 Aug 2014) in Javascript

Despite a global shift towards touch-oriented devices on the internet and the existence of a relatively old bug report, Google has decided not to add support for mobile/touch to their ChartRangeFilter for Google Charts (as of the time of writing). See for yourself:

Demo | Source – Doesn’t work on mobile. Frustrating!

This is really annoying, especially if you are dealing with a significant chunk of data that could take advantage of this functionality by allowing users to ‘zoom in’ on specific areas.

 

A Workaround (For Now)

Although we can’t get the ChartRangeFilter working on mobile, we can display something else instead for mobile devices such as the handy jQRangeSlider. To do so we’ll need to hook into the methods provided by google.visualization.ControlWrapper (which sits around the ChartRangeFilter).

In the source we have:

var controlWrapper = new google.visualization.ControlWrapper({
	controlType: 'ChartRangeFilter',
	...
});

We can update the selection in the ChartRangeFilter by calling the following on its ControlWrapper:

controlWrapper.setState({
	range: {
		start: new Date(2004, 01, 01),
		end: new Date(2006, 01, 01)
	}
});
controlWrapper.draw();

Combine this with a mobile UA check (terrible I know, but you can’t really use browser  feature detection for this) and a DateRangeSlider (I’m using dates on my X axis) and you get the following:

var is_mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
// ChartRangeFilter doesn't work on mobile. Use a dateRangeSlider to manipulate it
if ( is_mobile )
{
	$('#filter').hide();
	$('#filter_mobile').show();
 
	$( "#filter_mobile" ).dateRangeSlider({
		bounds: {
			min: new Date(2001, 1, 1),
			max: new Date(2013, 3, 1)
		},
		defaultValues: {
			min: new Date(2001, 1, 1),
			max: new Date(2013, 3, 1)
		},
		step: {
			months: 1
		},
		arrows: true,
		wheelMode: null
	}).bind('valuesChanged', function(e, data) {
		controlWrapper.setState({range: { start: data.values.min, end: data.values.max }});
		controlWrapper.draw();
	});
}

Demo

ChartRangeFilter workaround for mobile devices

ChartRangeFilter workaround for mobile devices

Try the demo below. View it on a mobile device (or use a mobile UA string). You get the standard Google Charts ChartRangeFilter for desktop and jQRangeSlider for mobile. Everything works nicely!

Demo | Source – Snazzy mobile-specific date range widget

Read More »

How to Mount a Broken EXT4 Drive

Posted June 2nd, 2013 (Updated 19 Jul 2013) in Linux

This morning I noticed one of my drives wasn’t mounted so I attempted to mount manually and got the following error message:

$ sudo mount /dev/sdi1 /mnt/my_drive/

mount: wrong fs type, bad option, bad superblock on /dev/sdi1,
missing codepage or helper program, or other error
In some cases useful info is found in syslog – try
dmesg | tail or so

Strange. Following the messages advice I checked out dmesg:

$ dmesg | tail

[ 213.962722] EXT4-fs (sdi1): no journal found

 

The Solution

If this happens to you, you can ignore the error and mount in readonly mode using the following command:

sudo mount -o loop,ro,noexec,noload /dev/sdi1 /mnt/your_broken_partition/

Thanks to Computer Forensics for their useful post on this issue.

ALWAYS BACKUP YOUR DATA

Read More »

Secure WordPress – Limit Logins to Specified Countries with CloudFlare

Posted April 9th, 2013 in PHP

As I’m sure is the case with just about every WordPress user, my site is constantly hit with failed login attempts from bots – usually originating from other countries. I had the idea last night to implement country-based login restrictions using CloudFlare’s IP Geolocation server variable.

My goal was to redirect redirect all users visiting the login page from countries other than Australia to the home page. This occurs before a login attempt can even be made.

Here’s how it’s done:

  • Go into CloudFlare settings and make sure the IP Geolocation option is turned onMake sure CloudFlare IP Geolocation is turned on
  • Add the following to your active themes functions.php file
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // Limit login countries - requires cloudflare
    add_action( 'wp_authenticate', 'login_failed', 1);
    function login_failed()
    {
    	if ( !isset($_SERVER["HTTP_CF_IPCOUNTRY"]) )
    		return;
     
    	if ( !in_array($_SERVER["HTTP_CF_IPCOUNTRY"], array('AU')) )	{
    		wp_redirect( home_url() );
    		exit;
    	}
    }

To test simply use a country other than your own. Once it’s confirmed working switch to your country and you’re good to go!

Read More »

Get MySQL Table Sizes

Posted March 19th, 2013 in Database

Here is a super simple SQL query to determine the size of all tables in a given database:

SELECT TABLE_NAME AS "Table",
	round(((data_length + index_length) / 1024 / 1024), 2) AS Size_in_MB
FROM information_schema.TABLES 
WHERE table_schema = 'my_db_name'
ORDER BY Size_in_MB DESC

This can be very useful when debugging for instance in figuring out which rogue plugin/module on your site is dumping hundreds of megs of data into your database.

Read More »

Fix Home and End Keys on Mac OS X

Posted March 18th, 2013 (Updated 10 Aug 2014) in Uncategorized

Disclaimer: The details of this post are shamelessly ripped from phatness.com. All credit to those guys, I just wanted a copy for myself for future reference.


On every OS ever, Home, End, Pg Up and Pg Down keys work like so:

- Home -> move the cursor to the beginning of the line
- End -> move the cursor to the end of the line
- Pg-Up -> move the cursor up the length of the viewport
- Pg-Dn -> move the cursor down the length of the viewport

But OSX in all its infinate wisdom decided that doesn’t make sense. Instead they should work like so:

- Home -> move (nothing, not even the cursor, just your view) to the beginning of the DOCUMENT
- End -> move (nothing, not even the cursor, just your view) to the end of the DOCUMENT
- Pg-Up -> move (nothing, not even the cursor, just your view) up the length of the viewport
- Pg-Dn -> move (nothing, not even the cursor, just your view) down the length of the viewport

Now I’m not one to criticise… but that’s stupid and anyone who likes it is stupid ;)

 

How to Fix

There’s a really useful open source utility out there called DoubleCommand which is highly recommended and I’m sure broadly used. If you want a non-application solution there are also some config files to edit to get the job done.

Most Applications

Create a file
/home/<username>/Library/KeyBindings/DefaultKeyBinding.dict and add the following:

{
    "\UF729"  = "moveToBeginningOfLine:";
    "$\UF729" = "moveToBeginningOfLineAndModifySelection:";
    "\UF72B"  = "moveToEndOfLine:";
    "$\UF72B" = "moveToEndOfLineAndModifySelection:";
    "\UF72C"  = "pageUp:";
    "\UF72D"  = "pageDown:";
}

Terminal

Terminal preferences

Terminal preferences

Open Terminal – Preferences – Settings – Keyboard. Edit each of the following setting their action to ‘send string to shell’.

Key		Escape Sequence
 
Home		\033[1~
End		\033[4~
Page Up		\033[5~
Page Down	\033[6~

Now open /home/<username>/.inputrc and add:

"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": history-search-backward
"\e[6~": history-search-forward
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word
set completion-ignore-case On

Other notes

Restart your machine for changes to take affect. Restarting individual applications also works if you can’t restart for whatever reason. I hear Firefox needs its own changes – if you happen to know what those are comment below and I’ll add them in.

Read More »

How to Drastically Speed Up WordPress with Redis

Posted March 16th, 2013 (Updated 25 Mar 2013) in Database, PHP

I recently came across a tutorial on sitting Redis infront of WordPress allowing for insanely fast page generation. I gave it a try and it really works, in fact I’m now using it on this very site! The best part however is the fact that the script requires absolutely no modification to your existing WordPress site save for 1 line of htaccess. Truly amazing.

Below I’ll detail my slightly modified version of Jim’s script along with some metrics.

 

Firstly, What is Redis and what will it do for me?

The Redis website describes Redis as

… an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain stringshasheslistssets and sorted sets.

What does this mean? Essentially it’s Memcached but more useful. Redis stores key-value pairs in memory and spits them out when requested. Unlike Memcached it has built in persistence but what’s most important to us is that it’s fast – very fast.

We’ll be using Redis to speed up our site by loading cached pages from it directly without even booting up WordPress. This will save a large amount of page generation time and get out site infront of our users’ eyeballs faster.

 

Exactly how much faster are we talking?

In my very unscientific tests, loading www.flynsarmy.com a bunch of times resulted in the following:

Before (Secs) After (Secs)
1.556
0.468
0.494
0.498
0.492
0.514
0.499
0.511
0.499
0.02001
0.00896
0.00883
0.00959
0.01472
0.00916
0.00915
0.00756
0.01989

As you can see from the table above this equates to a 20x to 50x speed increase and that was WITH W3 Total Cache installed! Results of course may vary but I think you get the picture.

Read More »

Edit WordPress Posts from the Front End

Posted March 5th, 2013 (Updated 10 Aug 2014) in PHP

I have a project coming up involving editing WordPress posts from the front end of the site. There are a bunch of plugins that let you do this the coolest of which seems to be Front-end Editor but I wanted to come up with my own solution. Luckily it turned out to be surprisingly quick and painless!

For this tutorial I’ll be editing the cafe custom post type from my last post.

Read More »

Adding Custom Post Types, Fields and Taxonomies in WordPress

Posted March 5th, 2013 (Updated 13 Mar 2013) in PHP

This information is pretty readily available on the internet but I figured I’d make my own post for safe keeping. I’ll be adding a custom post type (Cafes) with 3 custom fields (Website, Address and Phone) and a custom taxonomy (Countries).

The following code all goes in your functions.php file.

 

Custom Post Types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * Add Cafe post type
 */
function create_cafe_post_type() {
	register_post_type( 'cafes',
		array(
			'labels' => array(
				'name' => 'Cafes',
				'singular_name' => 'Cafe',
				'add_new' => 'Add New',
				'add_new_item' => 'Add New Cafe',
				'edit_item' => 'Edit Cafe',
				'new_item' => 'New Cafe',
				'view_item' => 'View Cafe',
				'search_items' => 'Search Cafes',
				'not_found' =>  'Nothing Found',
				'not_found_in_trash' => 'Nothing found in the Trash',
				'parent_item_colon' => ''
			),
			'public' => true,
			'publicly_queryable' => true,
			'show_ui' => true,
			'query_var' => true,
			//'menu_icon' => get_stylesheet_directory_uri() . '/yourimage.png',
			'rewrite' => true,
			'capability_type' => 'post',
			'hierarchical' => false,
			'menu_position' => null,
			'supports' => array('title','editor','thumbnail')
		)
	);
}
add_action( 'init', 'create_cafe_post_type' );

 

Custom Taxonomies

Taxonomies are basically tags for your post types. Add the following below the register_post_type call above:

1
2
3
4
5
6
7
//Cafe countries taxonomy
register_taxonomy("countries", array("cafes"), array(
	"hierarchical" => false,
	"label" => "Countries",
	"singular_label" => "Country",
	"rewrite" => true
));

 

Custom Fields

This is the hardest of the lot. It’s not really hard though, just alot of HTML to make the meta boxes. You can put any HTML you like in meta boxes, I just like to keep mine looking like standard WP fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
/**
 * Add cafe custom fields
 */
function add_cafe_meta_boxes() {
	add_meta_box("cafe_contact_meta", "Contact Details", "add_contact_details_cafe_meta_box", "cafes", "normal", "low");
}
function add_contact_details_cafe_meta_box()
{
	global $post;
	$custom = get_post_custom( $post->ID );
 
	?>
	<style>.width99 {width:99%;}</style>
	<p>
		<label>Address:</label><br />
		<textarea rows="5" name="address" class="width99"><?= @$custom["address"][0] ?></textarea>
	</p>
	<p>
		<label>Website:</label><br />
		<input type="text" name="website" value="<?= @$custom["website"][0] ?>" class="width99" />
	</p>
	<p>
		<label>Phone:</label><br />
		<input type="text" name="phone" value="<?= @$custom["phone"][0] ?>" class="width99" />
	</p>
	<?php
}
/**
 * Save custom field data when creating/updating posts
 */
function save_cafe_custom_fields(){
  global $post;
 
  update_post_meta($post->ID, "address", @$_POST["address"]);
  update_post_meta($post->ID, "website", @$_POST["website"]);
  update_post_meta($post->ID, "phone", @$_POST["phone"]);
}
add_action( 'admin_init', 'add_cafe_meta_boxes' );
add_action( 'save_post', 'save_cafe_custom_fields' );

 

Custom Templates

You may want your new post type to look different from standard posts. This can be done using custom templates. The WordPress codex cover custom post type templates nicely but I’ll quickly go over what I did for completeness. I’m using twentytwelve theme in my demo but this should apply for most themes.

  1. Duplicate single.php into single-<post type>.php
  2. Replace
    <?php get_template_part( 'content', get_post_format() ); ?>

    with

    <?php get_template_part( 'content', '<post type>' ); ?>
  3. Duplicate content.php into content-<post type>.php and modify however you like

 

Conclusion

And we’re done! Always remember to check the WordPress documentation for the various functions involved if you want to customize. Lots of useful information in there.

Read More »

How to Load WordPress Multi-Site in a script

Posted February 12th, 2013 (Updated 14 Mar 2013) in PHP

This morning I was loading WPMU in a custom script and all get_option() lookups were returning the details for the main blog despite being in a switch_to_blog() block. After a bit of debugging it turns out this was due to get_option() caching its values from the main blog and never expiring its cache when switching. There’s a pretty easy action you can use to fix this:

1
2
3
4
5
6
7
8
function switch_to_blog_cache_clear( $blog_id, $prev_blog_id = 0 ) {
    if ( $blog_id === $prev_blog_id )
        return;
 
	wp_cache_delete( 'notoptions', 'options' );
	wp_cache_delete( 'alloptions', 'options' );
}
add_action( 'switch_blog', 'switch_to_blog_cache_clear', 10, 2 );

Below is a script in its entirety for loading WPMU, switching to blog 31 and grabbing its name:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
 
$_SERVER['HTTP_HOST'] = 'mypolicedev.com';
 
ini_set('display_errors', true);
 
/**
 * BEGIN LOAD WORDPRESS
 */
function find_wordpress_base_path() {
	$dir = dirname(__FILE__);
	do {
		//it is possible to check for other files here
		if( file_exists($dir."/wp-config.php") ) {
			return $dir;
		}
	} while( $dir = realpath("$dir/..") );
	return null;
}
 
define( 'BASE_PATH', find_wordpress_base_path()."/" );
global $wp, $wp_query, $wp_the_query, $wp_rewrite, $wp_did_header;
require(BASE_PATH . 'wp-load.php');
 
function switch_to_blog_cache_clear( $blog_id, $prev_blog_id = 0 ) {
	if ( $blog_id === $prev_blog_id )
		return;
 
	wp_cache_delete( 'notoptions', 'options' );
	wp_cache_delete( 'alloptions', 'options' );
}
add_action( 'switch_blog', 'switch_to_blog_cache_clear', 10, 2 );
 
/**
 * END LOAD WORDPRESS
 */
 
switch_to_blog( 31 );
var_dump(get_bloginfo('name'));
restore_current_blog();

Read More »

Page 4 of 15« First...23456...10...Last »