Tag Archives: WordPress

Three ways to integrate BuddyPress in three presentations

In the last year or so, I’ve given a number of public presentations about BuddyPress. One of my main goals in giving these presentations to WordPress groups is always to convince WP developers to give BP a try. My angle on this has been “BuddyPress compatibility”: the idea that you can take existing WordPress functionality and, with just a bit of pixie dust and elbow grease, integrate it into BP. While there are countless ways that a WP plugin could integrate with BuddyPress, the big three are: (1) displaying group-specific content in groups, (2) displaying user-specific content on user pages, and (3) registering items in the activity stream.

As of this past Saturday, I’ve now given presentations on all three of these methods:

  1. BuddyPressifying a WordPress Plugin Using the Group Extension API (BuddyCamp Miami 2013)
  2. Herding Cats with the BuddyPress Activity Component (WordCamp Europe 2013)
  3. BuddyPressifying a WordPress Plugin Using BP_Component (WPSessions, June 21, 2014)

If you’re a WP developer who’s looking for an on-ramp into BuddyPress work, I think these presentations are a good place to get started.

Expunge non-public content from a WordPress/BuddyPress installation

It’s a common practice to create local WordPress development environments using a copy of the production database. But this can cause problems with a large production site, as the database can become very large, and it is full of non-public information that you may not want to make available to all members of the development team. This is especially problematic when running a plugin like BuddyPress, which allows users to create a great deal of content with various privacy levels.

To work around this problem for the CUNY Academic Commons, I wrote this plugin: cac-database-cleaner. It will remove all non-public data from a WP database, while still leaving an intact database image that can be used to populate a development environment.

WARNING – This is a dangerous tool, as it deletes large amounts of data. Under no circumstances should you install this plugin on a production site. To use: export your production database; import to a separate database and perform any manual changes necessary for the WordPress site to load locally (such as modification of your local hosts file); activate plugin and navigate to Dashboard > Network Admin > CAC Database Cleaner.

Again, do not use this plugin if you don’t know exactly what you’re doing.

Note that plugin support is ideosyncratic to the CUNY Academic Commons, where we run an old version of BuddyPress Docs, an old fork of BuddyPress Group Documents, a plugin called More Privacy Options, legacy bbPress forums, etc. Feel free to modify the plugin to work with whatever other data you’d like.

CSV export of WordPress data

I’m often asked by clients to export various bits of data from a WordPress site into a CSV file. For simple queries, this kind of technique is simplest. For more complex queries, I use PHP to do some of the heavy lifting. Below is some of the boilerplate I use for generating the proper headers, etc. Just swap out the filename and the query logic for your own, and visit wp-admin?bbg_export as a super admin.

Five years of BuddyPress

I started working with BuddyPress by accident. In February 2009, I responded to a tweet from my friend Matt Gold asking for help with a CSS issue on a site he was working on. That site was the still-in-beta CUNY Academic Commons, running on the still-in-beta BuddyPress. Within a few weeks, I was doing paid work for Matt’s project, working with BP (and WP, and web software in general) for the first time. And BuddyPress 1.0 came out just a few weeks after that.

Over the last five years, BuddyPress has taken over my professional life. I began by writing BP plugins. I started to contribute to BP itself through support and patches. I became a member and eventually a lead on the core team. My consultation work involves BuddyPress almost exclusively; this success (in terms of both money and impact) emboldened me to drop out of graduate school. People know me as “the BuddyPress guy”. When you type “boone gorges” into Google, it suggests “boone gorges buddypress”.

I feel very grateful to have stumbled into the project when I did. It aligns with many of my philosophical and political positions: the primacy of people over content, the importance of data ownership and free software, the fight against parasitic software vendors in public institutions. I’ve met some good friends through my association with BP. I’ve leveraged my expertise into a fun and comfortable career.

But the fact remains that it’s all been a fluke. When I realized it’s been five whole years, I couldn’t shake the thought: WTF. How strange to devote such a large part of one’s life to something that was such an accident. [Something something destiny something something forks in the road something.] I got lucky because I happened to stumble into something that was a particularly good fit for me. But I also took many leaps of faith along the way: agreeing to work on the CUNY Academic Commons when I had pretty much no idea what I was doing, submitting my first patches to BP, quitting my job, upping my rates, donating huge amounts of time to the free project instead of doing paid client work. I’m glad I had the guts to make each of these leaps.

Happy birthday to BuddyPress, and happy anniversary to me. Here’s to many more happy accidents!

Manually copy content and settings between sites in a WP network

I just had a request to copy the contents and settings from one site within a WordPress network to another within the same network. (The destination site is the “staging” version of the source.) Daniel Bachhuber’s Dictator along with the general wp-cli export/import tools are the ideal tools for this sort of thing, but due to some odd circumstances I wasn’t able to use them. So here’s a quick rundown of what I ended up doing. (This post mainly for my own records. If any step below is confusing to you, you probably should not be doing it this way. Use at your own risk!)

  • Get exports of the production db tables (as well as staging, for backup). I ended up crafting the following (614 is the ID of the production site):
    mysql -u [username] -p information_schema -B -N -e "SELECT table_name FROM tables WHERE table_name LIKE 'wp_614_%'" | xargs mysqldump -u [username] -p [database name] --add-drop-table --skip-lock-tables --quick --extended-insert --result-file=[/path/to/dumpfile.sql]
  • I downloaded that dumpfile and imported it into a local database, so that I could run it through https://github.com/interconnectit/Search-Replace-DB to do the necessary URL replacements. (Could’ve used wp-cli, but this way I didn’t need to have a functional local WP installation.)
  • Did a further search and replace to change instances of ‘wp_614_’ to ‘wp_860_’ (the staging site ID)
  • Uploaded that .sql file and imported
  • Next, I had to handle files. Normally this would take 30 seconds at the command line, but permissions were locked down on this server: my SSH user didn’t have proper permissions to modify some of the directories in blogs.dir. So I wrote a quick script that would run the necessary commands in PHP (as the webserver user), implemented as an mu-plugin: https://gist.github.com/boonebgorges/75e3ec70bd5177dab7dd

Again, use at your own risk.

Any major dude with half a heart surely will be at WordCamp Connecticut on May 10

A few months ago, I had the pleasure of speaking at the WordPress Stamford Meetup, organized by Clint Warren. I musta put a bug in his ear or something, because I got a follow-up email last month letting me know he was organizing the very first WordCamp Connecticut. I’ll be giving a talk about BuddyPress.

The organizers are still looking for speakers, so if you’re a WordPress person in the CT vicinity (Stamford is an easy Metro-North ride from NYC), please consider applying to present! And if you’re just looking to nerd out for a day, add yourself to the mailing list so you’ll know when tickets are available. DO IT

Recent Anthologize updates

Anthologize, you are neglected, but not forgotten!

In the past week or so, I’ve done two maintenance releases (0.7.2 and 0.7.3) for Anthologize. A few highlights:

  • Fixed some issues with the way TCPDF saves image files in a temporary cache. This should help to avoid the dreaded “TCPDF ERROR: Can’t open image file” fatal error when exporting to PDF on some server configurations.
  • Fixed some issues with the way that Anthologize’s JS and CSS files are loaded, for better compatibility with other plugins and with SSL wp-admin.
  • Fixed a bug that gave non-admins the ability to change settings on some multisite configurations.

Speaking of not forgotten, I haven’t forgotten my friends who supported my Anthologize campaign back in 2012. This post goes out to Eric A Mann, an outstanding WordPress developer and blogger. Thanks for supporting Anthologize, Eric!

Default Gravatar images and SSL

I have a client who runs a number of WordPress/BuddyPress sites over SSL. He noticed in the last few days that default Gravatar images – the images that Gravatar serves when there is no Gravatar associated with the queried email address – were not being served. The browser showed broken images, and when you attempted to load the associated https://secure.gravatar.com URL in a separate tab, you’d see the message “We cannot complete this request, remote data could not be fetched”.

After a bit of futzing around, I found this recent post by Eric Mann describing a similar issue with the Photon CDN feature in the Jetpack plugin. He managed to figure out that Automattic’s CDN service wasn’t fetching items that were served over HTTPS. (The fact that it ever worked was, apparently, a bug; that “bug” was recently fixed.)

It turns out that the same thing is true for Gravatar’s “Default Image” feature (unsurprising, as I assume it uses the same CDN as Photon). Gravatar lets you specify a local file that will be served if no actual Gravatar is found: <img src="http://www.gravatar.com/avatar/00000000000000000000000000000000?d=http%3A%2F%2Fexample.com%2Fimages%2Favatar.jpg" /> But, as of the last few weeks, if the value of the d= param is served over HTTPS only, Gravatar throws an error.

There are a couple strategies for working around the problem.

  • Use Gravatar’s defaults instead – Gravatar hosts a number of default images that you can use, instead of a local image. This is especially pertinent in the case of BuddyPress. BP’s default behavior is to construct Gravatar requests like this: http://www.gravatar.com/avatar/00000000000000000000000000000000?d=http%3A%2F%2Fexample.com%2Fimages%2Fwp-content%2Fplugins%2Fbuddypress%2Fbp-core%2Fimages%2Fmystery-man.jpg. The thing is that this mystery-man.jpg that ships with BuddyPress is the same image as what you get with ?d=mm. So an easy way around the problem of Gravatar reading from your SSL-protected site is to avoid Gravatar from making any requests to your site at all. In BuddyPress, use the following:
    function bbg_use_gravatar_mm() {
        return 'mm';
    }
    add_filter( 'bp_core_mysteryman_src', 'bbg_use_gravatar_mm' );
    
  • Allow non-SSL access to your default – As suggested in Eric’s post, you can tell your webserver that some of your content can be served over HTTP rather than HTTPS. For example, on one of the sites I’m working on, we force HTTPS for all requests using an .htaccess rule. I can amend it to allow an exception for the custom Gravatar default:
    RewriteCond %{HTTPS} off
    RewriteCond %{REQUEST_URI} !^/wp\-content/themes/yourtheme/images/default\-gravatar.jpg$
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]
    

    Then, force BuddyPress to tell Gravatar you want the non-SSL version of the fallback:

    function bbg_custom_default_avatar() {
        return set_url_scheme( get_stylesheet_directory_uri() . '/images/default-gravatar.jpg', 'http' );
    }
    add_filter( 'bp_core_mysteryman_src', 'bbg_custom_default_avatar' );
    

Even if you’re not using BuddyPress or WordPress, the same strategy applies: if you’re serving your whole site over HTTPS, tell Gravatar to use either one of its own images or one of your non-SSL-available images as its default.

Convert multi-db WordPress mysqldump to single-db

On a number of client sites, I use HyperDB or SharDB to spread a WordPress Multisite installation across multiple databases on a single server. However, in my local dev environments, it’s annoying to have thousands of databases. So I use the following technique to create a copy of the remote site that operates in a single database locally.

  1. Use mysqldump to get a backup file. The following command ensures that you don’t pull in information_schema or any other unrelated databases; you can add other DBs to ignore to the NOT IN list:
    $ mysql -u [username] -p -B -N -e "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mysql','tmp','innodb','information_schema','performance_schema')" | xargs mysqldump -u [username] -p --add-drop-table --skip-lock-tables --quick --extended-insert --result-file=[path/to/your/dumpfile.sql] --databases
    
  2. Use sed to remove all the ‘CREATE DATABASE’ and ‘USE’ lines in the dumpfile. This prevents the multiple databases from being created when importing locally.
    $ sed -i '' -e'/^CREATE DATABASE /d' /path/to/dumpfile.sql
    $ sed -i '' -e'/^USE /d' /path/to/dumpfile.sql
    
  3. Get the dumpfile to your local machine, and import:
    $ mysql -u [username] -p -e "create database foo"
    $ mysql -u [username] -p foo < ~/path/to/local/dumpfile.sql
    

    (or whatever technique you use for mysql imports) (don’t know why my code formatter is converting < to &lt; but you get the idea).

Getting started with WordPress plugin development

I got an email with the following question, and figured I may as well answer publicly. The question comes from someone who’s an experienced programmer, but has never worked with WordPress before.

[...] I wondered if you had some helpful advice on learning the basics of WP plugin development. I’m mostly hoping there are frameworks/libraries that the community is currently using.

I don’t know of a widely-used library of general WP plugin development tools. Partly this is because WP itself partially qualifies as a “library”, insofar as it provides ready-to-use functions for saving data to the database, URL routing, template loading, user management, etc. And partly it’s because the architecture of WP is so wide open that it’d be difficult to build a more generalized library that covered even a majority of the possible modifications you might make to stock WordPress.

That said, here are a few useful tools that I know of:

  • The official WP documentation on writing a plugin is good for learning about plugin manifests as well as a top-level overview of the aspects of plugin development.
  • The official Plugin API page is also a good starting point. It explains WP’s hook system, which is the foundation for plugin development.
  • Pippin Williamson has written a series called Plugin Development 101 that features a set of video tutorials on common plugin development techniques. Costs a couple bucks, but Pippin is a smart dude and I’m sure the videos are a really good way to get started.
  • There are a couple of tools that can be used to generate boilerplate and basic file setup for plugins. The ones I know of are https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate and the wp scaffold plugin command in WP-CLI.
  • The book Professional WordPress Plugin Development is very solid, and a good investment for those who like to learn this kinda stuff through books.

My #1 piece of advice to people getting started with WP plugin development is to find a plugin that does something sorta like what they are trying to do and to reverse engineer it. For me, this is far faster and more practical than any hello-world tutorial or sequential set of lessons. YMMV.

If anyone has other suggestions, please feel free to add them in the comments.