I came across a super interesting post at WPBits about automating the wordpress installation process. Some of the parts about where some of the functions are located in WP that allow you to change certain things on the installation are outdated since the post is from 2007, but the concept remains perfectly intact. If you find yourself installing a lot of WordPress blogs and are tired of always having to delete the “This is your First Post” post, changing the permalinks etc. then you can take advantage of this little trick.
Trolling the Source Code Like a Boss
If you are cruising through source (because there is plenty of stuff that isn’t well documented yet in the Codex) you will see
/** Include user install customize script. */ if ( file_exists(WP_CONTENT_DIR . '/install.php') ) require (WP_CONTENT_DIR . '/install.php');
in /wp-admin/includes/upgrade.php. Now this is interesting because it means that when WordPress installs (or upgrades) it will look for a file called install.php in your /wp-content folder… or whatever you are using instead of the default /wp-content folder. This file doesn’t exist by default but it gives you a chance to run some functions of your own during the installation process (since /wp-admin/includes/upgrade.php is required by /wp-admin/install.php)
My First CuSTOM INSTALL.PHP
I followed WPBit’s example and decided to show off my new power over WordPress by putting the following into my custom /wp-content/install.php file.
No Bacon for You <br/>Evil Superpowers <?php exit();?>
This obviously isn’t helpful, but it is a good proof of concept and let’s you know that you have all the power. Of course…
With great power comes great responsibility. – Uncle Ben
Functions We Can Hijack for Our Own Purposes
As WPBits explains in more detail, some of the ideal functions to tweak would be:
- wp_install()
- wp_install_defaults()
- wp_new_blog_notification()
- wp_upgrade()
All of these functions are now (currently version 3.3.1) in /wp-admin/includes/upgrade.php and they are pluggable, meaning they come with an if(function_exists()) wrapper that lets you define your own versions to override their behavior.
Since wp_install_defaults() is the culprit for creating those useless “first post” posts and pages, we’re going to target it. I copied the entire function to my own file: /wp-content/install.php and then hacked out all the parts that inserted the first post, first page, the default links in the blogroll (sorry WordPress), and changed the default category from Uncategorized to General. You can also adjust the widgets that are activated by default, but I thought that was going too far.
I also wanted to change some options, like permalinks, time zone, size of the post editor, banning emoticons, etc. So I added a bunch of update_option() commands. Just because I thought it’d be super clever, I updated the ping list, moderate and blacklist comment terms from text files by using file_get_contents().
Automagically Creating Myself as an Admin
I usually install WP for someone else, I decided that I wanted to create my client’s account on install and automatically create my own admin account. I might reverse this process as I don’t like how the install’s welcome email doesn’t include a link to the login screen. I know that you just tack on wp-login.php but a newbie client might not. At the same time, the way I have it means I never have to change my credentials in the file… which I prefer for now.
Anyway, I initially overrode the default wp_install() file to do this, by repeating the process of copying the function from /wp-admin/includes/upgrade.php to my own install.php, but it turns out that I can just create a new user from the function I already have. In that case, I decided to only override one core function.
Here’s the code I used. Remember to use it at your own risk. This is really targeted at people who know what they are doing with WordPress and are installing it on a regular basis. Take note to change the username and email address for the account you are creating for yourself… currently they are left as USERNAME and YOU@YOUREMAIL.COM. Right now it generates a random password, but that could easily be changed to always assign yourself the same password.
<?php /** * Override Default Installation Content * do not create empty page, first test post, default links, default comment, etc */ function wp_install_defaults($user_id) { global $wpdb, $wp_rewrite, $current_site, $table_prefix; /* * BEGIN KIA TWEAKS * Customize Some Options */ // Set Timezone //$timezone = "America/New_York"; $timezone = "America/Chicago"; //$timezone = "America/Denver"; //$timezone = "America/Los_Angeles"; update_option('timezone_string',$timezone); // Start of the Week update_option('start_of_week',0); //0 is Sunday, 1 is Monday and so on // Disable Smilies update_option('use_smilies', 0); // Increase the Size of the Post Editor update_option('default_post_edit_rows',40); // Update Ping Services // http://mrjimhudson.com/wordpress-update-services-use-a-larger-ping-list/ if ( file_exists(WP_CONTENT_DIR . '/KIA-ping-list.txt') ) { $services = file_get_contents('KIA-ping-list.txt', true); update_option('ping_sites',$services); } // Update Comment Moderation List // http://perishablepress.com/wordpress-blacklist-characters/ if ( file_exists(WP_CONTENT_DIR . '/KIA-comment-moderation-list.txt') ) { $modlist = file_get_contents('KIA-comment-moderation-list.txt', true); update_option('moderation_keys',$modlist); } // Update Comment Blacklist // http://www.pureblogging.com/2008/04/29/create-a-comment-blacklist-in-wordpress-download-my-list-of-spam-words/ if ( file_exists(WP_CONTENT_DIR . '/KIA-comment-blacklist.txt') ) { $blacklist = file_get_contents('KIA-comment-blacklist.txt', true); update_option('blacklist_keys',$blacklist); } // Don't Organize Uploads by Date update_option('uploads_use_yearmonth_folders',0); // Update Permalinks update_option('selection','custom'); update_option('permalink_structure','/%post_id%/%postname%/'); $wp_rewrite->flush_rules(); // Default category $cat_name = __('General'); /* translators: Default category slug */ $cat_slug = sanitize_title(_x('General', 'Default category slug')); /* * Create Self as Admin User. If the user already exists, the user tables are * being shared among blogs. Just set the role in that case. */ $self_id = username_exists('USERNAME'); if ( !$self_id ) { $self_password = wp_generate_password( 12, false ); $self_id = wp_create_user('USERNAME', $user_password, 'YOU@YOUREMAIL.COM'); update_user_option($self_id, 'default_password_nag', true, true); wp_new_user_notification( $self_id, $self_password ); } $self = new WP_User($self_id); $self->set_role('administrator'); /* * END KIA TWEAKS */ /* * END KIA TWEAKS */ if ( global_terms_enabled() ) { $cat_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = %s", $cat_slug ) ); if ( $cat_id == null ) { $wpdb->insert( $wpdb->sitecategories, array('cat_ID' => 0, 'cat_name' => $cat_name, 'category_nicename' => $cat_slug, 'last_updated' => current_time('mysql', true)) ); $cat_id = $wpdb->insert_id; } update_option('default_category', $cat_id); } else { $cat_id = 1; } $wpdb->insert( $wpdb->terms, array('term_id' => $cat_id, 'name' => $cat_name, 'slug' => $cat_slug, 'term_group' => 0) ); $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $cat_id, 'taxonomy' => 'category', 'description' => '', 'parent' => 0, 'count' => 1)); $cat_tt_id = $wpdb->insert_id; // Default link category $cat_name = __('Blogroll'); /* translators: Default link category slug */ $cat_slug = sanitize_title(_x('Blogroll', 'Default link category slug')); if ( global_terms_enabled() ) { $blogroll_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = %s", $cat_slug ) ); if ( $blogroll_id == null ) { $wpdb->insert( $wpdb->sitecategories, array('cat_ID' => 0, 'cat_name' => $cat_name, 'category_nicename' => $cat_slug, 'last_updated' => current_time('mysql', true)) ); $blogroll_id = $wpdb->insert_id; } update_option('default_link_category', $blogroll_id); } else { $blogroll_id = 2; } $wpdb->insert( $wpdb->terms, array('term_id' => $blogroll_id, 'name' => $cat_name, 'slug' => $cat_slug, 'term_group' => 0) ); $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $blogroll_id, 'taxonomy' => 'link_category', 'description' => '', 'parent' => 0, 'count' => 7)); $blogroll_tt_id = $wpdb->insert_id; // Set up default widgets for default theme. update_option( 'widget_search', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) ); update_option( 'widget_recent-posts', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) ); update_option( 'widget_recent-comments', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) ); update_option( 'widget_archives', array ( 2 => array ( 'title' => '', 'count' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) ); update_option( 'widget_categories', array ( 2 => array ( 'title' => '', 'count' => 0, 'hierarchical' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) ); update_option( 'widget_meta', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) ); update_option( 'sidebars_widgets', array ( 'wp_inactive_widgets' => array ( ), 'sidebar-1' => array ( 0 => 'search-2', 1 => 'recent-posts-2', 2 => 'recent-comments-2', 3 => 'archives-2', 4 => 'categories-2', 5 => 'meta-2',), 'sidebar-2' => array ( ), 'sidebar-3' => array ( ), 'sidebar-4' => array ( ), 'sidebar-5' => array ( ), 'array_version' => 3 ) ); if ( ! is_multisite() ) update_user_meta( $user_id, 'show_welcome_panel', 1 ); elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) ) update_user_meta( $user_id, 'show_welcome_panel', 2 ); if ( is_multisite() ) { // Flush rules to pick up the new page. $wp_rewrite->init(); $wp_rewrite->flush_rules(); $user = new WP_User($user_id); $wpdb->update( $wpdb->options, array('option_value' => $user->user_email), array('option_name' => 'admin_email') ); // Remove all perms except for the login user. $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'user_level') ); $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'capabilities') ); // Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.) TODO: Get previous_blog_id. if ( !is_super_admin( $user_id ) && $user_id != 1 ) $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $wpdb->base_prefix.'1_capabilities') ); } }
I don’t keep this file live on the server, but I suppose you could if you dropped an .htaccess file into the /wp-content folder and banned access to your custom install.php file
<Files install.php> Order Allow,Deny Deny from all </Files>
That about sums it all up. Let me know what cool jedi tricks you are doing with your custom install.php file!
Downloads