Changing Permalink Settings Programmatically ☆

| April 9, 2010

Using plugin code to modify the permalink settings of a WordPress blog is surprisingly not straight forward. The options involved (of which their are three), need to be modified in three places: the option values themselves, the rewrite rules in the WordPress database, and the .htaccess (or equivalent) files on disk. Update just one, and it won’t work.

Looking for a solution to this problem, I pulled out a chunk of code from wp-admin/options-permalink.php. After a few small modifications I ended up with the following function:

function modify_permalinks($permalink_structure, $category_base, $tag_base){
	global $wp_rewrite;
		
	require_once(ABSPATH . 'wp-admin/includes/file.php');
	require_once(ABSPATH . 'wp-admin/includes/misc.php');
	
	
	# get paths
	
	$home_path = get_home_path();
	$iis7_permalinks = iis7_supports_permalinks();


	# set the structure

	$permalink_structure = preg_replace('#/+#', '/', '/' . $permalink_structure);
	$wp_rewrite->set_permalink_structure($permalink_structure);

	$category_base = preg_replace('#/+#', '/', '/' . $category_base);
	$wp_rewrite->set_category_base($category_base);

	$tag_base = preg_replace('#/+#', '/', '/' . $tag_base);
	$wp_rewrite->set_tag_base($tag_base);
	

	# check if there is a file to rewrite

	if ( $iis7_permalinks ) {
		if ( ( ! file_exists($home_path . 'web.config') && win_is_writable($home_path) ) || win_is_writable($home_path . 'web.config') )
			$writable = true;
		else
			$writable = false;
	} else {
		if ( ( ! file_exists($home_path . '.htaccess') && is_writable($home_path) ) || is_writable($home_path . '.htaccess') )
			$writable = true;
		else
			$writable = false;
	}
	
	
	# flush the rules
	
	update_option('rewrite_rules', FALSE);
	$wp_rewrite->flush_rules($writable);	
}

So far it seems to work with any action hook in both WordPress and WordPress MU (durring registration, when modifying an option, etc.), but I haven’t tried everything.