├── README ├── fabfile.py ├── scripts ├── na-createblog.php ├── na-install.php ├── na-options.php ├── na-postinstall.php └── na-setup-plugins.php └── wp-config-mamp.php /README: -------------------------------------------------------------------------------- 1 | UPDATE: We no longer use this. This has been replaced by http://github.com/newsapps/wp-project-tools 2 | 3 | Wordpress Network push-button deployment and automated setup 4 | Copyright 2010 Chicago Tribune 5 | 6 | This tutorial is written for folks on Mac OS X. Much of the instructions will work on any Unix variant. If you're on Windows, I'd love to hear how you got this to work. 7 | 8 | You'll need to have fabric and lxml installed. 9 | 10 | $ sudo easy_install fabric lxml 11 | 12 | Lets grab the scripts for this tutorial. You can clone them from github here. Next you need to grab the latest wordpress. Download and unzip the wordpress archive. You want to take all the files from the wordpress folder created by the archive and move them to the folder you just cloned from github with all your fancy new scripts. 13 | 14 | $ git clone http://github.com/newsapps/wordpress-deploy.git wordpress-deploy 15 | $ cd wordpress-deploy 16 | $ fab get_wordpress 17 | 18 | To get this new mess of code to do anything interesting, you will need an Apache, PHP and MySQL stack on your machine. We do all wordpress development locally and deploy stuff to a server when we want to test or show off our work. Since we all work on Mac OS X, we decided to use MAMP for development. We chose MAMP because it's a tight package that made it trivial for everyone to get running quickly. Feel free to setup your stack however you like, but this tutorial assumes you're using MAMP. 19 | 20 | http://www.mamp.info/en/index.html 21 | 22 | Out of the box, MAMP needs a few tweaks before it will serve our project. Download the latest version, install it to your Applications folder and run the MAMP application. MAMP will immediately start Apache and MySql and open its web control panel in your browser. 23 | 24 | Find MAMP on your dock and click it to bring up the status window. Click "Preferences...". Under the "Ports" tab, set the Apache port to 80. Wordpress gets cranky if you try to run it on a port other than port 80. Under the "Apache" tab, change the "Document Root" to the project folder with your new scripts and wordpress code. 25 | 26 | If you've ever turned on web sharing, turn it off now. If you already have MySQL installed on your machine, you'll probably run into trouble. 27 | 28 | You need to add MAMP's MySQL binaries to your path, so you can use mysql from the command line. 29 | 30 | $ export PATH=$PATH:/Applications/MAMP/Library/bin 31 | 32 | Add this command to the end of your '~/.bash_profile' so you can always access the MySQL commands. 33 | 34 | $ echo "export PATH=$PATH:/Applications/MAMP/Library/bin" >> ~/.bash_profile 35 | 36 | Add the demo wordpress domain name to your hosts file. 37 | 38 | $ sudo bash -c 'echo "127.0.0.1 my-wp-blog.dev" >> /etc/hosts' 39 | (If you're on Leopard or earlier, your hosts file is /private/etc/hosts) 40 | 41 | At this point you should be able to fire up a wordpress site with the demo settings. Just run the bootstrap fabric command. 42 | 43 | $ fab bootstrap 44 | 45 | You should have wordpress running now. Visit http://my-wp-blog.dev. You also should have network blogs running at http://my-wp-blog.dev/frogs/ and http://my-wp-blog.dev/rabbits/. 46 | 47 | Configuration juicyness 48 | 49 | These scripts are just a starting point. The ones we use for TribLocal are heavily customized. Dig through them and tweak to your hearts content. We've annotated them a bunch, but ask us more questions if you find something that isn't clear. 50 | 51 | The scripts: 52 | * fabfile.py 53 | Where all the deployment settings are put. Use this to setup your production or staging server or to change settings for local development. 54 | * scripts/na-options.php 55 | Most important file. Holds all the config information for the Wordpress side of the automatic setup. 56 | * scripts/na-install.php 57 | First script that runs. Installs the Wordpress database, root blog and network. 58 | * scripts/na-postinstall.php 59 | Second script that runs. Configures the root blog and network with settings from the na-options.php. 60 | * scripts/na-createblog.php 61 | Script that creates a network blog. Pass it an index, uses that index to fetch data about the blog it should create from the $sites array in na-options.php. 62 | * scripts/na-setup-plugins.php 63 | Enables plugins. 64 | 65 | One more thing 66 | 67 | Something that always bothered me about Wordpress is the way the domain name is stored in the database. You can't just dump and load the database in a new location without also moving the domain name. We want it to be push-button to deploy an identical copy of the site in multiple places. 68 | 69 | So I wrote a few fabric commands to shuttle a Wordpress database across servers and domain names. 70 | 71 | $ fab dump_db 72 | $ fab load_db 73 | $ fab reload_db 74 | 75 | These commands will create or load data/dump.sql.bz2. They'll correct the domain name in the Wordpress database to whatever you have defined in your fabfile. Super useful. It just pipes the database content through sed to replace the domain names. 76 | 77 | -------------------------------------------------------------------------------- /fabfile.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Chicago Tribune News Applications fabfile 3 | # No copying allowed 4 | 5 | import os 6 | import subprocess 7 | import urllib 8 | 9 | from fabric.api import * 10 | from fabric.contrib.console import confirm 11 | from fabric.context_managers import cd 12 | 13 | from getpass import getpass 14 | 15 | """ 16 | Base configuration 17 | """ 18 | env.project_name = "my-wp-blog" 19 | env.wpdomain = 'my-wp-blog.dev' 20 | env.path = os.getcwd() 21 | 22 | # Do you want to use git or svn for deployment? 23 | env.strategy = 'git' 24 | 25 | # If you said svn, where should I checkout from? 26 | env.svnrepo = '' 27 | 28 | # If you said git, where should I clone from and which branch should I checkout? 29 | env.gitrepo = '' 30 | env.gitbranch = 'master' 31 | 32 | # These are the credentials for the wordpress. They should match your wp-config.php. 33 | env.db_host = 'localhost' 34 | env.db_name = env.project_name 35 | env.db_wpuser_name = env.project_name 36 | env.db_wpuser_pass = 'changeme' #make up something complicated for the password 37 | 38 | # Super user name and pass for adding users and databases to mysql 39 | env.db_root_user = "root" 40 | env.db_root_pass = "root" 41 | 42 | # This is the config file that will get installed on bootstrap 43 | env.config_file = 'wp-config-mamp.php' 44 | 45 | # Fix permissions throughout the deployment process. You may need to use this 46 | # if perms are getting messed up. 47 | env.fix_perms = False 48 | 49 | # This defaults the run and sudo functions to local, so we don't have to duplicate 50 | # code for local development and deployed servers. 51 | env.sudo = local 52 | env.run = local 53 | 54 | # Where should I get Wordpress?? 55 | env.wp_tarball = "http://wordpress.org/latest.tar.gz" 56 | 57 | """ 58 | Environments 59 | """ 60 | def production(): 61 | """ 62 | Work on production environment 63 | """ 64 | env.settings = 'production' 65 | env.hosts = ['example.com'] 66 | env.user = '' 67 | env.path = '' 68 | env.wpdomain = 'example.com' 69 | env.db_root_user = 'wpcustomuser' 70 | env.db_root_pass = '' 71 | env.config_file = 'wp-config-production.php' 72 | env.db_host = 'db.example.com' 73 | env.db_name = 'wp_custom_database' 74 | check_env() 75 | 76 | def staging(): 77 | """ 78 | Work on staging environment 79 | """ 80 | env.settings = 'staging' 81 | env.hosts = ['staging.example.com'] 82 | env.user = '' 83 | env.path = '' 84 | env.wpdomain = 'staging.example.com' 85 | env.db_root_user = 'wpsuperuser' 86 | env.db_root_pass = '' 87 | env.config_file = 'wp-config-staging.php' 88 | check_env() 89 | 90 | """ 91 | Commands - setup 92 | """ 93 | def git_clone_repo(): 94 | """ 95 | Do initial clone of the git repository. 96 | """ 97 | with settings(warn_only=True): 98 | run('git clone %(gitrepo)s %(path)s' % env) 99 | 100 | def git_checkout(): 101 | """ 102 | Pull the latest code on the specified branch. 103 | """ 104 | with cd(env.path): 105 | if env.branch != 'master': 106 | with settings(warn_only=True): 107 | run('git checkout -b %(gitbranch)s origin/%(gitbranch)s' % env) 108 | run('git checkout %(gitbranch)s' % env) 109 | run('git pull origin %(gitbranch)s' % env) 110 | 111 | def svn_checkout(): 112 | """ 113 | Checkout the site 114 | """ 115 | env.svn_user = prompt('SVN Username: ') 116 | env.svn_pass = getpass('Enter SVN Password: ') 117 | 118 | with cd(env.path): 119 | run('svn co %(repo)s . --username %(svn_user)s --password %(svn_pass)s' % env) 120 | 121 | """ 122 | Commands - deployment 123 | """ 124 | def setup(): 125 | """ 126 | Setup the site 127 | """ 128 | if env.strategy == 'git': 129 | git_clone() 130 | git_checkout() 131 | elif env.strategy == 'svn': 132 | svn_checkout() 133 | 134 | fix_perms() 135 | 136 | def deploy(): 137 | """ 138 | Deploy new code to the site 139 | """ 140 | if env.strategy == 'git': 141 | git_clone() 142 | git_checkout() 143 | elif env.strategy == 'svn': 144 | svn_checkout() 145 | 146 | fix_perms() 147 | 148 | """ 149 | Commands - data 150 | """ 151 | def bootstrap(): 152 | print("\nStep 1: Database and basic Wordpress setup") 153 | 154 | with cd(env.path): 155 | env.run('cp -P %(config_file)s wp-config.php' % env) 156 | 157 | fix_perms() 158 | 159 | create_db() 160 | env.run('curl -s http://%(wpdomain)s/scripts/na-install.php' % env) 161 | 162 | print("\nStep 2: Setup plugins") 163 | 164 | env.run('curl -s http://%(wpdomain)s/scripts/na-setup-plugins.php' % env) 165 | 166 | print("\nStep 3: Cleanup, create blogs") 167 | 168 | env.run('curl -s http://%(wpdomain)s/scripts/na-postinstall.php' % env) 169 | 170 | if confirm("Create child blogs?"): create_blogs() 171 | 172 | def create_db(): 173 | if not env.db_root_pass: 174 | env.db_root_pass = getpass("Database password: ") 175 | 176 | env.run('mysqladmin --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s create %(db_name)s' % env) 177 | env.run('echo "GRANT ALL ON * TO \'%(db_wpuser_name)s\'@\'localhost\' IDENTIFIED BY \'%(db_wpuser_pass)s\';" | mysql --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s %(db_name)s' % env) 178 | 179 | def load_db(dump_slug='dump'): 180 | env.dump_slug = dump_slug 181 | if not env.db_root_pass: 182 | env.db_root_pass = getpass("Database password: ") 183 | with cd(env.path): 184 | env.run("bzcat data/%(dump_slug)s.sql.bz2 |sed s/WPDEPLOYDOMAN/%(wpdomain)s/g |mysql --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s %(db_name)s" % env) 185 | 186 | def dump_db(dump_slug='dump'): 187 | env.dump_slug = dump_slug 188 | if not env.db_root_pass: 189 | env.db_root_pass = getpass("Database password: ") 190 | with cd(env.path): 191 | env.run("mysqldump --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s --lock-all-tables %(project_name)s |sed s/%(wpdomain)s/WPDEPLOYDOMAN/g |bzip2 > data/%(dump_slug)s.sql.bz2" % env) 192 | 193 | def destroy_db(): 194 | if not env.db_root_pass: 195 | env.db_root_pass = getpass("Database password: ") 196 | 197 | with settings(warn_only=True): 198 | env.run('mysqladmin -f --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s drop %(project_name)s' % env) 199 | env.run('echo "DROP USER \'%(db_wpuser_name)s\'@\'localhost\';" | mysql --host=%(db_host)s --user=%(db_root_user)s --password=%(db_root_pass)s' % env) 200 | 201 | def destroy_attachments(): 202 | with cd(env.path): 203 | env.run('rm -rf wp-content/blogs.dir') 204 | 205 | def reload_db(dump_slug='dump'): 206 | destroy_db() 207 | create_db() 208 | load_db(dump_slug) 209 | 210 | def create_blogs(): 211 | response = "Success" 212 | base_cmd = 'curl -s http://%(wpdomain)s/scripts/na-createblog.php' % env 213 | i=0 214 | while "Success" in response: 215 | response = env.run(base_cmd + '?new_blog_index=%s' % i) 216 | i+=1 217 | print(response) 218 | print("Created %s blogs" % str(i-1)) 219 | 220 | def fix_perms(): 221 | if env.fix_perms: 222 | env.sudo("chown -Rf %(apache_user)s:%(apache_group)s %(path)s; chmod -Rf ug+rw %(path)s;" % env) 223 | 224 | def wrap_media(): 225 | with cd(env.path): 226 | env.run('tar zcf data/media.tgz wp-content/blogs.dir/* wp-content/uploads/*') 227 | print('Wrapped up media.\n') 228 | 229 | def unwrap_media(): 230 | with cd(env.path): 231 | env.run('tar zxf data/media.tgz') 232 | print('Unwrapped media.\n') 233 | 234 | def put_media(): 235 | check_env() 236 | put('data/media.tgz','%(path)s/data/media.tgz' % env) 237 | print('Put media on server.\n') 238 | 239 | def get_media(): 240 | check_env() 241 | get('%(path)s/data/media.tgz' % env, 'data/media.tgz') 242 | print('Got media from the server.\n') 243 | 244 | """ 245 | Deaths, destroyers of worlds 246 | """ 247 | def shiva_the_destroyer(): 248 | """ 249 | Remove all directories, databases, etc. associated with the application. 250 | """ 251 | try: 252 | check_env() 253 | env.run('rm -Rf %(path)s/* %(path)s/.*;' % env) 254 | destroy_db() 255 | except NameError, e: 256 | with settings(warn_only=True): 257 | env.run('rm .htaccess') 258 | env.run('rm wp-config.php') 259 | destroy_db() 260 | 261 | """ 262 | Utilities 263 | """ 264 | def check_env(): 265 | require('settings', provided_by=[production, staging, development, testing]) 266 | env.sudo = sudo 267 | env.run = run 268 | 269 | def get_wordpress(): 270 | print("Downloading and installing Wordpress...") 271 | with cd(env.path): 272 | env.run('curl -s %(wp_tarball)s | tar xzf - ' % env) 273 | env.run('mv wordpress/* .') 274 | env.run('rmdir wordpress') 275 | print("Done.") 276 | 277 | def install_plugin(name, version='latest'): 278 | try: 279 | from lxml.html import parse 280 | from lxml.cssselect import CSSSelector 281 | except ImportError: 282 | print("I need lxml to do this") 283 | exit() 284 | 285 | print("Looking for %s..." % name) 286 | 287 | url = "http://wordpress.org/extend/plugins/%s/" % name 288 | p = parse("%sdownload/" % url) 289 | sel = CSSSelector('.block-content .unmarked-list a') 290 | dload_elems = sel(p) 291 | 292 | if not dload_elems: 293 | print("Can't find plugin %s" % name) 294 | exit() 295 | 296 | #first is latest 297 | if version == 'latest': 298 | plugin_zip = dload_elems[0].attrib['href'] 299 | version = dload_elems[0].text 300 | else: 301 | plugin_zip = None 302 | for e in dload_elems: 303 | if e.text == 'version': 304 | plugin_zip = e.attrib['href'] 305 | break 306 | 307 | if not plugin_zip: 308 | print("Can't find plugin %s" % name) 309 | exit() 310 | else: 311 | print("Found version %s of %s, installing..." % (version, name) ) 312 | with cd(env.path + "/wp-content/plugins"): 313 | env.run('curl -s %s -o %s.%s.zip' % (plugin_zip, name, version) ) 314 | env.run('unzip -n %s.%s.zip' % (name, version) ) 315 | 316 | if raw_input("Read instructions for %s? [Y|n]" % name) in ("","Y"): 317 | subprocess.call(['open', url]) 318 | -------------------------------------------------------------------------------- /scripts/na-createblog.php: -------------------------------------------------------------------------------- 1 | hide_errors(); 35 | if ($subdomain_install) { 36 | $id = wpmu_create_blog($site['slug'].".".$hostname, "", $site['name'], 1, $options, 1); 37 | } else { 38 | $id = wpmu_create_blog($hostname, "/".$site['slug'], $site['name'], 1, $options, 1); 39 | } 40 | $wpdb->show_errors(); 41 | 42 | 43 | 44 | if (!is_wp_error( $id )) { 45 | //doing a normal flush rules will not work, just delete the rewrites 46 | switch_to_blog( $id ); 47 | 48 | // we delete the rewrites because flushing them does not work if the originally 49 | // loaded blog is the main one, deleteing them will force a propper flush on that site's first page. 50 | delete_option( 'rewrite_rules' ); 51 | 52 | // Delete the first post 53 | wp_delete_post( 1, true ); 54 | 55 | // Delete the about page 56 | wp_delete_post( 2, true ); 57 | 58 | //Configure categories 59 | wp_delete_category(1); 60 | $inserted_cats = array(); 61 | foreach ($categories as $cat) { 62 | $cat_id = wp_insert_category( $cat ); 63 | $inserted_cats[$cat_id] = $cat; 64 | } 65 | 66 | // Create the Section Menu 67 | $menu_id = wp_create_nav_menu( 'Main', array( 'slug' => 'main' ) ); 68 | 69 | // Assign it to the sections theme location 70 | $theme = get_current_theme(); 71 | $mods = get_option( 'mods_' . $theme ); 72 | $mods['nav_menu_locations']['sections'] = $menu_id; 73 | update_option( 'mods_' . $theme, $mods ); 74 | 75 | // Create the menu items 76 | foreach ( $inserted_cats as $cat_id => $cat ) : 77 | 78 | if ( in_array( $cat['cat_name'], $section_nav ) ) : 79 | 80 | $menu_item_id = wp_update_nav_menu_item( 81 | $menu_id, 82 | 0, 83 | array( 84 | 'menu-item-title' => $cat['cat_name'], 85 | 'menu-item-type' => 'taxonomy', 86 | 'menu-item-object' => 'category', 87 | 'menu-item-object-id' => $cat_id, 88 | 'menu-item-position' => 1, 89 | 'menu-item-status' => 'publish' 90 | ) 91 | ); 92 | 93 | wp_set_object_terms( $menu_item_id, (int) $menu_id, 'nav_menu' ); 94 | 95 | endif; 96 | 97 | endforeach; 98 | 99 | // flush rewrite rules 100 | delete_option( 'rewrite_rules' ); 101 | 102 | print("Success - ".$site['name']." setup"); 103 | } else { 104 | die($id->get_error_message()); 105 | } 106 | 107 | ?> 108 | -------------------------------------------------------------------------------- /scripts/na-install.php: -------------------------------------------------------------------------------- 1 | tables( 'ms_global' ) as $table => $prefixed_table ) 53 | $wpdb->$table = $prefixed_table; 54 | 55 | install_network(); 56 | 57 | $ms_install_result = populate_network( 58 | $network_id, 59 | $hostname, 60 | $admin_email, 61 | $network_title, 62 | $base, 63 | $subdomain_install 64 | ); 65 | 66 | if (is_wp_error( $ms_install_result ) && $ms_install_result->get_error_code() != 'no_wildcard_dns') { 67 | print($ms_install_result->get_error_message() . "\n"); 68 | die("Network setup failed"); 69 | } 70 | 71 | print("Network setup finished\n"); 72 | 73 | // lets write some files 74 | 75 | // Write the .htaccess file 76 | $htaccess_file = 'RewriteEngine On 77 | RewriteBase ' . $base . ' 78 | RewriteRule ^index\.php$ - [L] 79 | 80 | # uploaded files 81 | RewriteRule ^' . ( $subdomain_install ? '' : '([_0-9a-zA-Z-]+/)?' ) . 'files/(.+) wp-includes/ms-files.php?file=$' . ( $subdomain_install ? 1 : 2 ) . ' [L]' . " 82 | 83 | RewriteCond %{REQUEST_FILENAME} -f [OR] 84 | RewriteCond %{REQUEST_FILENAME} -d 85 | RewriteRule ^ - [L] 86 | RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L] 87 | RewriteRule ^(.*/)?sitemap.xml wp-content/sitemap.php [L] 88 | RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L] 89 | RewriteRule . index.php [L]"; 90 | 91 | fwrite(fopen("../.htaccess", 'w'), $htaccess_file); 92 | 93 | // Update the wp-config file 94 | $configFile = file('../wp-config.php'); 95 | $newConfig = ""; 96 | foreach ($configFile as $line_num => $line) { 97 | if (substr($line,0,16) == "/* That's all, s") { 98 | $newConfig .= "define( 'MULTISITE', true ); 99 | define( 'SUBDOMAIN_INSTALL', "; 100 | $newConfig .= $subdomain_install ? 'true' : 'false'; 101 | $newConfig .= ");\n"; 102 | $newConfig .= "\$base = '$base'; 103 | define( 'DOMAIN_CURRENT_SITE', '$hostname' ); 104 | define( 'PATH_CURRENT_SITE', '$base' ); 105 | define( 'SITE_ID_CURRENT_SITE', 1 ); 106 | define( 'BLOG_ID_CURRENT_SITE', 1 );\n"; 107 | } 108 | $newConfig .= $line; 109 | } 110 | 111 | fwrite(fopen("../wp-config.php", 'w'), $newConfig); 112 | 113 | print("Wrote config files\n"); 114 | 115 | print("Success\n") 116 | 117 | ?> 118 | -------------------------------------------------------------------------------- /scripts/na-options.php: -------------------------------------------------------------------------------- 1 | "", 28 | // Active theme 29 | 'template' => 'twentyten', 30 | 'stylesheet' => 'twentyten', 31 | 'current_theme' => 'Twenty Ten', 32 | 'timezone_string' => 'America/Chicago', 33 | 'use_trackback' => '1', 34 | 'comment_registration' => '0', 35 | 'comment_whitelist' => '', 36 | 'category_base' => '/category', 37 | 'tag_base' => '/tag', 38 | 'default_ping_status' => 1, 39 | 'comments_notify' => 1 40 | ); 41 | 42 | // Prepare Network settings 43 | 44 | // Some settings are serialized and saved in the database. Arrays seem 45 | // to be serialized differently depending on how they are defined. So 46 | // do it this way or else stuff will break. 47 | 48 | // set the allowed theme for all sites 49 | $allowed_themes = array(); 50 | $allowed_themes["twentyten"]=true; 51 | 52 | // enable the add image button for network sites 53 | $mu_media_buttons = array(); 54 | $mu_media_buttons['image'] = '1'; 55 | 56 | // Network settings 57 | $site_options = array( 58 | // Default network theme 59 | 'allowedthemes' => $allowed_themes, 60 | 61 | // Network settings 62 | 'dashboard_blog' => 1, 63 | // 'admin_notice_feed' => 'http://'.$hostname.'/feed/', 64 | 'registrationnotification' => 'no', 65 | 'add_new_users' => 1, 66 | 'registration' => 'user', 67 | 'welcome_user_email' => "Dear User,\n\nYour new account is set up.\n\nYou can log in with the following information:\n\tUsername: USERNAME\n\tPassword: PASSWORD\nLOGINLINK\n\nThanks!\n\n--The Team @ SITE_NAME", 68 | 'mu_media_buttons' => $mu_media_buttons, 69 | 'upload_space_check_disabled' => 1, 70 | 71 | // Set max upload file size 72 | 'fileupload_maxk' => '10000', 73 | ); 74 | 75 | // Define network blogs to create. The keys 'slug' and 'name' are required for each. 76 | // You can also define blog specific options by adding more 'key'=>'value' pairs. 77 | $sites = array( 78 | array( 79 | 'slug' => 'rabbits', // for the url for this blog. e.g. slug.example.com or example.com/slug 80 | 'name' => 'My blog about rabbits' // this is the name for this blog to be used everywhere 81 | ), 82 | array( 83 | 'slug' => 'frogs', 84 | 'name' => 'My blog about frogs' 85 | ) 86 | ); 87 | 88 | // Posts to add automatically. 89 | // For the root blog only. 90 | $posts = array( 91 | array( // FAQ 92 | 'post_type' => 'page', 93 | 'post_author' => 1, 94 | 'post_status' => 'publish', 95 | 'post_title' => 'F.A.Q.', 96 | 'post_name' => 'faq', 97 | 'post_content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' 98 | ), 99 | array( // Contact us 100 | 'post_type' => 'page', 101 | 'post_author' => 1, 102 | 'post_status' => 'publish', 103 | 'post_title' => 'Contact us', 104 | 'post_name' => 'contact-us', 105 | 'post_content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' 106 | ), 107 | array( // Help 108 | 'post_type' => 'page', 109 | 'post_author' => 1, 110 | 'post_status' => 'publish', 111 | 'post_title' => 'Help', 112 | 'post_name' => 'help', 113 | 'post_content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' 114 | ) 115 | ); 116 | 117 | // Categories to add to each blog. 118 | // For child blogs only. 119 | $categories = array( 120 | array( 121 | 'cat_name' => 'Sports', 122 | 'category_nicename' => 'sports', 123 | 'category_description' => '', 124 | ), 125 | array( 126 | 'cat_name' => 'News', 127 | 'category_nicename' => 'news', 128 | 'category_description' => '' 129 | ), 130 | array( // replaces Uncategorized 131 | 'cat_ID' => 1, 132 | 'cat_name' => 'Other', 133 | 'category_nicename' => 'other', 134 | 'category_description' => '' 135 | ) 136 | ); 137 | 138 | // Create a menu on each blog and add these categories as items. 139 | // For child blogs only. 140 | $menu_categories = array( 141 | 'News', 142 | 'Sports' 143 | ); 144 | 145 | // Create these users in all blogs. 146 | $users = array( 147 | array('alissaswango','Alissa Swango','aswango@tribune.com','',NULL,'administrator'), 148 | 149 | ); 150 | 151 | ?> 152 | -------------------------------------------------------------------------------- /scripts/na-postinstall.php: -------------------------------------------------------------------------------- 1 | $val) { 23 | update_option($key, $val); 24 | } 25 | print("Default blog options set\n"); 26 | 27 | // Set network options 28 | foreach ($site_options as $key => $val) 29 | update_site_option($key, $val); 30 | 31 | print("Default network options set\n"); 32 | 33 | // Build a menu for the root blog pages 34 | $menu_id = wp_create_nav_menu( 'Pages', array( 'slug' => 'pages' ) ); 35 | 36 | // Assign it to the 'pages' menu theme location 37 | $theme = get_current_theme(); 38 | $mods = get_option( 'mods_' . $theme ); 39 | $mods['nav_menu_locations']['pages'] = $menu_id; 40 | update_option( 'mods_' . $theme, $mods ); 41 | 42 | // Add each page to the root blog then add the page to the 'pages' menu 43 | if ($posts) { 44 | foreach ($posts as $post) { 45 | $post_id = wp_insert_post($post); 46 | if ($post_id == 0) 47 | print("Error adding ".$post['post_title']."\n"); 48 | else { 49 | print("Added ".$post['post_title']."\n"); 50 | $mitem_id = wp_update_nav_menu_item( 51 | $menu_id, 52 | 0, 53 | array( 54 | 'menu-item-title' => $post['post_title'], 55 | 'menu-item-type' => 'post_type', 56 | 'menu-item-object' => 'post', 57 | 'menu-item-object-id' => $post_id, 58 | 'menu-item-position' => 1, 59 | 'menu-item-status' => 'publish') 60 | ); 61 | wp_set_object_terms( $mitem_id, (int) $menu_id, 'nav_menu' ); 62 | print("Added to menu\n"); 63 | } 64 | } 65 | 66 | print("Added some posts\n"); 67 | } 68 | 69 | ?> 70 | -------------------------------------------------------------------------------- /scripts/na-setup-plugins.php: -------------------------------------------------------------------------------- 1 | get_error_messages() as $err ) 46 | print("FAILED: {$err}\n"); 47 | } else { 48 | print("Activated\n"); 49 | } 50 | 51 | } 52 | 53 | foreach( $site_plugins as $plugin ) { 54 | 55 | echo "Activating " . $plugin . "... "; 56 | $result = activate_plugin( $plugin ); 57 | 58 | if ( is_wp_error( $result ) ) { 59 | foreach ( $result->get_error_messages() as $err ) 60 | print("FAILED: {$err}\n"); 61 | } else { 62 | print("Activated\n"); 63 | } 64 | 65 | } 66 | 67 | do_action( 'plugins_loaded' ); 68 | 69 | print("Success\n"); 70 | 71 | 72 | ?> 73 | -------------------------------------------------------------------------------- /wp-config-mamp.php: -------------------------------------------------------------------------------- 1 |