Tag Archives: WordPress

Looking back at 2010

2010 was a wild year for me, one that I’ll look back on as a turning point in my professional and personal life. For that reason I thought I might take stock of the past year. (Here’s 2009’s post.) If you are one of those snobs who think that year-end retrospectives are schlocky, feel free to get the hell out of my blog.

As 2010 opened, I was working full-time as the educational technologist by Queens College. I believed strongly (and continue to believe) in the importance of the work I was doing there, but I already knew a year ago that I wouldn’t be able to stay at the job for much longer. I identified as an ed tech, and part of the (really great) ed tech community, but it was a label that never really felt right. When people asked what I did for a living, I hesitated. I left the job near the end of May.

Since then, I have been supporting myself doing custom web development, almost exclusively using BuddyPress. In the last six months, I’ve transitioned from an uneasy edtech to a confident (though still n00bish in many ways) developer. It’s a classification that feels better in many ways. Moving into development has allowed me to be personally productive in ways that the structures of my old career simply couldn’t support. I produce a lot of software that is used by a lot of people; moreover, I am moving toward a position where I get to select only those projects that are of independent interest to me. Measured like this, 2010 was the most productive year of my life, made possible by the career move (and the new self-identification that came with it).

My move into development is not without misgivings. As an educational technologist, working in the confines of a traditional university, there were always connections (sometimes tenuous, but always discernable) between my day job and my identity as a graduate student. Granted, in the time I was at Queens – first as a graduate fellow and then as a full-timer – I made next to no progress on my dissertation. But the fact that I was in a university, and enabling teaching and learning in a hands-on way, kept me in constant communication with my inner philosopher: drawing on my teaching experience, speaking in academic tones with faculty members, engaging in debates on the goals and methods of educational technology in ways that never strayed far from the kinds of discourse I learned in the seminar room. My work as a developer, in contrast, is much less explicitly academic; while some of my projects (notably, the CUNY Academic Commons) have sustained my contact with the university, mostly I am paid to think about software and websites rather than anything else. In the short term, this will undoubtedly be a good thing – I attribute the progress I’ve made on my thesis in the semester since I left Queens College to the fact that my day job provides me with some much-needed release from the mental anguish of the university life. But the more I make a name for myself as a developer, where ‘developer’ is unqualified by ‘academic’ or any similar modifier, the more I have to make conscious decisions about how (and whether) I want my paying gigs to connect with my academic interests. It’s an issue I’ll continue to wrestle with in 2011.

Paralleling my move into a development career has been an increased participation in the WordPress world. In July I was made a moderator on the buddypress.org support forums. In October, I was brought on as a committing developer for the BuddyPress project. I spoke dozens of times through 2010 on WordPress and BuddyPress, at WordCamps, meetups, conferences, THATCamps, and various other fancy places. At the beginning of 2010 I felt like I’d staked out a position on the outskirts of the WordPress community; at the end of 2010, I feel like I’m much closer to its center. And while I could live without the occasional drama, tunnel-vision, and personality cultishness of some WordPressophiles, for the most part it has been a real treat getting to know, and getting to work with, so many of the best WP developers. It’s broken me out of that other echo chamber I come from (academia), made me a much better coder, and introduced me to some really fabulous folks.

In 2010, I also got more and more tangled up with the digital humanities community. In July, I spent a week at the Center for History and New Media for the One Week | One Tool project, where I was on a team that built Anthologize. I attended a number of THATCamps and was witness to a number of Twitter arugments of truly epic proportions. And while I could live without the occasional drama, tunnel-vision, and personality cultishness of some DigitalHumanitiesophiles, for the most part it has been a real treat getting to know, and getting to work with, so many of the best digital humanists. (Is there an echo in here?) My intellectual connection with DH is such that it is hard for me not to put scare quotes around ‘digital humanities’ every time I write it: I am an academic, and I do extensive work with digital technology, but the connection between the two is not manifest in my own work. Still, DH in 2010 has been an exciting place to locate oneself, with cool projects, smart people, and the occasional Big Idea rising to the top over the course of the year.

I continued being a dork in 2010. I came in 66th at the American Crossword Puzzle Tournament (breaking 50 in 2011! You read it here first!). I switched from QWERTY to Dvorak. I visited the Googleplex. I wrote a lot about pizza and barbecue. I made the decision to stop buying Apple products. I completed Angry Birds. I wrote 45 blog posts on Teleogistic, with a smattering of posts elsewhere. Teleogistic got 960 comments. I wrote many tens of thousands of lines of code, much of which was terrible, and much of which is sadly hidden forever on client servers, but some of which is free and helpful to many.

On June 5, 2010, I got married. I mention this last not because it is the least important event of the year but because it is the most. The process of preparing for a wedding, with the help and support of so many friends and loved ones, was something I will never forget. The wedding day was the most perfect day I can remember. And the girl I married – well, duh, she is the best part of 2010, or of any year.

The changes of 2010 were more significant for me than any year since I was in college. Nearly all of those changes have been for the better. I have some exciting plans for 2011, but for now I am happy to reflect on the year that was. For me, it was a good one.

Wildcard email whitelists in WordPress and BuddyPress

Cross-posted on the CUNY Academic Commons Development Blog

WordPress (and before that WPMU) has long had a feature that allows admins to set a whitelist of email domains for registration (Limited Email Registration). On the Commons, we need to account for a lot of different domains, some of which are actually dynamic – but they are all of the form *.cuny.edu. WP doesn’t support this kind of wildcards, but we’ve got it working through a series of customizations.

These first two functions form the heart of the process. The first one hooks to the end of the BP registration process, looks for email domain errors, and then sends the request to the second function, which does some regex to check against the wildcard domains you’ve specified. This is BP-specific, but I think you could make it work with WPMS just by changing the hook name.


function cac_signup_email_filter( $result ) {
	global $limited_email_domains;

if ( !is_array( $limited_email_domains ) )
		$limited_email_domains = get_site_option( 'limited_email_domains' );

$valid_email_domain_check = cac_wildcard_email_domain_check( $result['user_email'] );

if( $valid_email_domain_check ) {
		if ( isset( $result['errors']->errors['user_email'] ) )
			unset( $result['errors']->errors['user_email'] );
	}

return $result;
}
add_filter( 'bp_core_validate_user_signup', 'cac_signup_email_filter', 8 );

function cac_wildcard_email_domain_check( $user_email ) {
	global $limited_email_domains;

if ( !is_array( $limited_email_domains ) )
		$limited_email_domains = get_site_option( 'limited_email_domains' );

if ( is_array( $limited_email_domains ) && empty( $limited_email_domains ) == false ) { 
		$valid_email_domain_check = false;
		$emaildomain = substr( $user_email, 1 + strpos( $user_email, '@' ) );
		foreach ($limited_email_domains as $limited_email_domain) {
			$limited_email_domain = str_replace( '.', '.', $limited_email_domain);        // Escape your .s
			$limited_email_domain = str_replace('*', '[-_.a-zA-Z0-9]+', $limited_email_domain);     // replace * with REGEX for 1+ occurrence of anything
			$limited_email_domain = "/^" . $limited_email_domain . "/";   // bracket the email with the necessary pattern markings
			$valid_email_domain_check = ( $valid_email_domain_check or preg_match( $limited_email_domain, $emaildomain ) );
		}
	}

return $valid_email_domain_check;
}

Before WP 3.0, this was enough to make it work. The latest WP does increased sanitization on the input of the limited_email_domains field, however, which makes it reject lines like *.cuny.edu. The following functions add an additional field to the ms-options.php panel that saves the limited domains without doing WP’s core checks. (Beware: bypassing WP’s checks like this means that there are no safeguards in place for well-formedness. Be careful about what you type in the field, or strange things may happen.)


function cac_save_limited_email_domains() {
	if ( $_POST['cac_limited_email_domains'] != '' ) {
		$limited_email_domains = str_replace( ' ', "n", $_POST['cac_limited_email_domains'] );
		$limited_email_domains = split( "n", stripslashes( $limited_email_domains ) );

$limited_email = array();
		foreach ( (array) $limited_email_domains as $domain ) {
				$domain = trim( $domain );
			//if ( ! preg_match( '/(--|..)/', $domain ) && preg_match( '|^([a-zA-Z0-9-.])+$|', $domain ) )
				$limited_email[] = trim( $domain );
		}
		update_site_option( 'limited_email_domains', $limited_email );
	} else {
		update_site_option( 'limited_email_domains', '' );
	}
}
add_action( 'update_wpmu_options', 'cac_save_limited_email_domains' );

function cac_limited_email_domains_markup() {
	?>

<h3><?php _e( 'Limited Email Domains That Actually Work' ); ?></h3>

<table class="form-table">
	<tr valign="top">
		<th scope="row"><label for="cac_limited_email_domains"><?php _e( 'Limited Email Registrations' ) ?></label></th>
		<td>
			<?php $limited_email_domains = get_site_option( 'limited_email_domains' );
			$limited_email_domains = str_replace( ' ', "n", $limited_email_domains ); ?>
			<textarea name="cac_limited_email_domains" id="limited_email_domains" cols="45" rows="5">
			<br />
			<?php _e( 'If you want to limit site registrations to certain domains. One domain per line.' ) ?>
		</td>
	</tr>
	</table>

<?php
}
add_action( 'wpmu_options', 'cac_limited_email_domains_markup' );

Extending Anthologize: Part 2

In my last post, I gave a brief overview of what happens when you click the Export Project button in Anthologize, with an eye toward demonstrating the role that third party plugins (written by people Just Like You!) can play in extending the software. In this post, I’ll flesh out some of those details.

Step 1: Anthologize, meet my format

Anthologize has what I like to think of as two internal APIs: the WordPress-facing API, and the theming API. The first step is to let Anthologize know that your format exists, which you’ll do by using the key function in the WP-facing API: anthologize_register_format(). (Check out how the WPAPI functions work in the source.) You should call anthologize_register_format() in a function hooked to anthologize_init, which ensures that it won’t fire before Anthologize is ready for it. Here’s a simple example:
[code language=”php”]
function register_my_anthologize_format() {
$name = ‘example_format’;
$label = ‘My Anthologize Format’;
$loader_file = dirname(__FILE__) . ‘/base.php’;

anthologize_register_format( $name, $label, $loader_file );
}
add_action( ‘anthologize_init’, ‘register_my_anthologize_format’ );
[/code]

anthologize_register_format_option() takes three arguments. The first is the name that Anthologize will use internally as a unique key for your format. The second is the name that users will see on the Export screen radio button and elsewhere in the interface. (It’s a good idea to set a textdomain for your strings so that they can be translated – eg $label = __( 'My Anthologize Format', 'my-anthologize-plugin' );.) The third argument is the absolute server path of your main translator file, the file that will be loaded at export time.

You can read a more in-depth example, embedded in a loader class, in this bare-bones plugin that I built for testing purposes. And the definitive examples, of course, can be found in the way that Anthologize registers its native export formats (yum, we love eating our own dog food!).

What does this give you? First, it makes your format available as a format option on the second screen of the export process:



Second, it gives your format a Publishing Options page. Since we haven’t registered any options yet, we get the bare minimum, the shortcode toggle that all formats get:



Third – and this is the big thing – anthologize_register_format() tells Anthologize that, if the user has selected your format on the export screens, the TEI document containing the project data will be handed off to the translator file whose path you specified when you registered the format. That’s where the format translation itself happens.

Step 2: Gimme some options

One of the big thoughts behind the Anthologize plugin architecture is to model WordPress’s design philosophy, which is to provide relatively few options in the core product but to allow for arbitrarily extended functionality by plugins. That’s the purpose behind anthologize_register_format_option(), the second pillar of Anthologize’s WP-facing API. anthologize_register_format_option() gives a framework for plugins to register any kind of option associated with their custom format, provides all the integrated markup for presenting those options to users, and passes along the user’s choices to the Anthologize TEI document used for format translation.

Format options can also be loaded at anthologize_init, though you should be careful to load them after the format itself. I’ll do that by using an add_action priority:
[code language=”php”]
function register_my_anthologize_format_options() {
$website_name = ‘website’;
$website_label = ‘Website’;
$website_type = ‘textbox’;

anthologize_register_format_option( ‘example_format’, $website_name, $website_label, $website_type );
}
add_action( ‘anthologize_init’, ‘register_my_anthologize_format_options’, 15 );
[/code]
(Note that the first argument is the unique $name of the format I intend to associate the option with.) This registers a plain textbox with the label ‘Website’:



You can also register checkboxes, if you need a Boolean:
[code language=”php”]
$option_name = ‘include_dedication’;
$option_label = ‘Include Dedication?’;
$option_type = ‘checkbox’;

anthologize_register_format_option( ‘example_format’, $option_name, $option_label, $option_type );
[/code]


Or you can register dropdowns:
[code language=”php”]
$fontface_format_name = ‘example_format’;
$fontface_option_name = ‘font-face’;
$fontface_label = ‘Font Face’;
$fontface_type = ‘dropdown’;
$fontface_values = array(
‘courier’ => ‘Courier’,
‘georgia’ => ‘Georgia’,
‘garamond’ => ‘Garamond’
);
$fontface_default = ‘georgia’;

anthologize_register_format_option( $fontface_format_name, $fontface_option_name, $fontface_label, $fontface_type, $fontface_values, $fontface_default );
[/code]
This kind of option highlights some of the other possible arguments that anthologize_register_format_option() will take: an array of possible values, and a default selected value:


All the options you provide, and in particular the options selected by the user at export time, are handed to your main translator file at the very end of the Anthologize export process.

So that’s how you get your format and its options registered on the WordPress side of things. Stay tuned for a discussion of how translators might be built.

Are you a potential plugin developer with ideas about how this API might evolve to better suit your purposes? Hop onto the dev list.

Extending Anthologize: Part 1

Anthologize has seen two version releases since its initial launch in August. Much of the progress since then (aside from some smallish – but needed – features and bugfixes) has been centered on the development of a plugin architecture for Anthologize, a system that will allow individuals to build custom output formats for their Anthologize content in a relatively straightforward way. Anthologize development team member (and metadata badass) Patrick Murray-John has been hard at work on this project: creating prototype plugins, writing blog posts about the plugin process, and of course building large parts of API itself. In this series of posts, I’d like to augment some of Patrick’s specific musings with a general explanation of how Anthologize works, and how the plugin API lets you tap into it. Think of it as an introduction to Anthologize plugin building.

First, a brief peek under the hood. Anthologize’s tagline is “Use the power of WordPress to transform online content into an electronic book.” How does Anthologize take you from point A – your WordPress content – to point B – your ebook? When you press the Export button on the final Export Project screen, you set into motion a two-step process.

Step 1: WordPress to TEI(ish)

WordPress content is stored in the wp_posts database table, and is typically accessed using WP’s “loop”, which is a set of iterative and indexical functions that make it easy to get and display post data in whichever way you’d like. When you hit the final Export button, Anthologize catches the form submit and hands things off to the format translator, which will get the content out of the database. We’ll use PDF as our example. The main translator file is base.php. That file acts like a top-level manager for all the things that have to be done in order for PDFs to be generated. The first important thing that any export format has to do is to call up the content of the project, which it does by instantiating the TeiDom class.

In many ways, TeiDom is the workhorse of Anthologize. Using the session data passed to it from the PDF base.php file – data that includes the project id, the desired page size, the content of the dedication, stuff like that – it uses a variation on The Loop to collect each part and item from an Anthologize project. Those objects, along with their metadata, are then fed into an empty TEI template file before getting handed back to the individual export format translator.

Why the middleman? Early in the development process, the team made a few decisions about the way that Anthologize ought to operate. First, though it’s currently being developed as a WordPress plugin, we should anticipate a time when much of Anthologize could be ported to another CMS or to a standalone application. If format translators like PDF had to dig directly into the WP database, or were forced to use The Loop to get project data, then they’d have to be refactored when the data lived somewhere other that WP. TEI is a platform-independent format, and since format translators like the PDF generator communicate only with the TeiDom (not directly with WordPress), they should be fairly platform-independent as well. Second, if we were going to have a middleman, we wanted it to be one with extremely broad expressive power, and one for which standards and translation techniques already exist. By choosing TEI, we open the door for armies of archivists, librarians, and other such format wizards, armed with XSLT ninjitsu. (In fact, that’s how Anthologize dev team member Patrick Rashleigh built the Anthologize epub generator!)

In the header for this section, I say TEI(ish) rather than TEI. That’s because the Anthologize middleman TEI layer is not the kind of TEI that your local text-encoder might expect. In particular, the content of your WordPress blog posts, which is already marked up with HTML, is untouched in the export process. A true TEI markup of your text would mean lots of manual encoding, so we just pass it along as-is. This untouched HTML post content, however, is embedded in a larger TEI framework for holding the metadata and generally explaining the structure of the project document. It’s not necessarily the kind of document you could use to build a richly marked-up text visualization, but it works well for the purposes of simple presentation.

Step 2: TEI to your format

Once the format generator (remember our friend templates/pdf/base.php?) gets the TEI document back from the TeiDom workhorse – which is essentially shared by all Anthologize export formats – the format-specific work can begin. PDF uses its own custom TEI-to-PDF class, along with an included PDF generation library, to parse the TeiDom object and turn it into something that, when delivered to your browser, is understood as a PDF. This, of course, is the hard part of building a translator, and is very format-specific.

The cool part about this part of the process, though, is the amount of flexibility that is emerging from the Anthologize architecture. Different format translators can deal with data in different ways; to wit:

  • The built-in PDF generator uses XPaths and some basic PHP loopage to format the final document. It’s also got some custom helper methods (eg get_book_title()) that it uses to make the the rendering code a bit easier to use.
  • The built-in ePub generator uses XSL transformations to move from the TEI document to the HTML-esque ePub output.
  • Patrick MJ has been working on a set of theming functions that will allow plugin authors to construct a loop very similar to the WordPress post Loop for the display of their data.
  • Because of the nature of PHP applications, export formats could always bypass Anthologize’s TEI and other API options and head directly for the WP database, using some embedded WP_Query/have_posts() loops.

Once your parser has turned Anthologize TEI data into the format necessary for your chosen format, you’ll need to deliver it to the browser by sending the write headers (here’s how ePub does it as an example).

In my next blog post, I’ll use an example to show how a plugin can register itself with Anthologize to take advantage of all these goodies.

New BuddyPress plugin: BP Group Reviews

I’m working on a project that needs to allow users to leave reviews of groups, kinda like buddypress.org does with plugins. So, with Andy’s permission, I cleaned up, packaged, and extended his code into a new plugin, BP Group Reviews. It allows users to leave a star rating and a text review of any group on your BuddyPress installation.

Lessons from the Google Summer of Code Mentor Summit

A few quick thoughts about the Google Summer of Code Mentor Summit, which I attended last weekend.

Google Summer of Code is a program, run by Google, which encourages open source development by paying college students to undertake summer coding projects with various open source projects. I co-mentored two projects for WordPress, and was one of the lucky few from among WP’s fifteenish mentors to get a trip to the Googleplex in Mountain View.

The Summit was organized as an unconference. On Saturday, attendees proposed session topics on a big scheduling board, and indicated their interest in other suggested sessions with stickers. This being a supremely geeky conference, I didn’t understand about half of the session titles.

A few takeaways, in no particular order:

  • Process matters. A lot. Probably 2/3 of the sessions I attended were devoted to project workflow: version control, code review, various kinds of testing. Probably some of the focus on process is due to the fact that it constitutes common ground between even those individuals whose software projects are quite different from each other. But I think it also speaks to the importance of workflow that really works, especially in the decidedly non-top-down world of open-source development communities.
  • WordPress seems pretty far behind the curve in terms of development infrastructure. Take version control: WordPress is the only project I heard about all weekend that still uses (or is not in the process of moving away from) centralized version control like Subversion. Git seemed like the most popular platform (there was a whole session on migrating massive project repos from SVN to Git, which was probably my favorite session of the weekend). I came away with lots of ideas for how the WP and BuddyPress development processes might be improved (and, more importantly, why it might be worthwhile to pursue these ideas), which I’ll be working on in the upcoming weeks and months.
  • More generally, I came away realizing that WordPress devs (and probably other kinds of devs, but this is what I know!) have a lot to learn from the way that similar software development projects are run. I was part of some extremely interesting conversations with core developers from Drupal and TYPO3 and was really, really impressed with the way the way that their development workflow informs and enables better software. Some WordPress fans have a tendency (sometimes joking, sometimes not) to disparage other projects like this, an attitude that can prevent us from learning a lot from each other. That’s a real shame, and it’s something I’d like to rail against.

I met some great people and learned a lot at the Summit. Many thanks to Google for footing the bill, to WordPress for selecting me to go, and to Stas and Francesco for their cool GSoC projects!

Joining the BuddyPress commit team

This weekend at WordCamp NYC, John James Jacoby announced that I, along with Paul Gibbs, have been promoted to core committers on the BuddyPress project. Needless to say, I’m honored and extremely excited.

For my academic friends who might not know what this means, here’s a (very brief) description of open-source development model used by WordPress (and, by extension, BuddyPress). Anyone who downloads the BuddyPress software can view and modify the source code at will. Likewise, anyone can report bugs, suggest enhancements, or file actual patches (small bits of code that, when added to the distribution version of the software, fix bugs or add features) on the BuddyPress bug tracker, which is the communication hub for the developers who work on the software. However, only a small handful of individuals can “commit” to the “core”. In other words, while anyone can submit code for consideration, only core committers can add those patches to the version of the software that is distributed via wordpress.org. Being added as a committer means that the existing committers (Andy, John, and Marshall) trust and respect my work enough to, in effect, hand me the keys to the car.

It’s a very cool thing for me because I don’t have any formal background in programming or in software. Before roughly the spring of 2009, I had only a smattering of programming knowledge, and had never cracked the hood of WordPress or of BuddyPress. My work on the CUNY Academic Commons plunged me deep into the world of WordPress development. I found a natural home in the BuddyPress community, which is full of smart people thinking not just about how software works, but also about how it can enhance the ways we engage with each other online. I’m certain that I wouldn’t have been promoted to this position if I hadn’t been willing (and encouraged) to share, whether it be the free time I’ve spent writing patches for BuddyPress, helping others out on the forums, or writing code that is freely available (and supported with a smile!). It’s a testament to the fact that the extra effort it sometimes takes to share and to do one’s work in the open can come back to you many times over.

I’m looking forward to the next stages of BuddyPress development!

New BuddyPress plugin: BP Lotsa Feeds

I’ve been working on a project recently with Kevin Prentiss and the other fine folks at Red Rover. Kevin is a big believer in the power of feeds, and I’m a big believer in the power of BuddyPress’s activity component, and together we realized that BuddyPress’s RSS support for its rich activity content is a bit lacking.

This new plugin, BP Lotsa Feeds, is meant to address the issue. It activates RSS feeds for just about everything in BuddyPress, from an individual member’s sitewide comments, to new group memberships for specific groups, to individual forum topics.

Read more about the plugin on its home page, and follow its development on Github. Thanks to Red Rover for sponsoring a cool plugin.

Using Github with wordpress.org plugin SVN

Like this tutorial? Check out my updated and more comprehensive Git/Github/wordpress.org tutorial at https://teleogistic.net/2011/05/revisiting-git-github-and-the-wordpress-org-plugin-repository/.

I’m on a never-ending quest to come up with a good local environment that will support the kind of WordPress plugin development that I enjoy So Very Much. I’ve only just recently begun using Github for version control and already I can’t imagine living without it. But doing WP plugin development in Github is not totally straightforward, because wordpress.org’s plugin repository uses SVN. When it comes time to release a new version on the wordpress.org repo, it’s simply not practical to merge changes manually and manage two different version histories. I wanted a setup where I could use Github for everyday development, but would connect to WP SVN when I was ready to release.

There are lots of posts out there on how to use git-svn:

I couldn’t get any of the methods to work the way I wanted. But by mashing a few of them together, I have what is, I think, a workable setup. Here are the steps.

  1. If you don’t already have one, create a Github repository for your work. I’ll assume here that you have configured Git on your machine, with git-svn installed as well.
  2. Create a directory for your working copy. I use several local WP installations for plugin development, the main one of which is named Doris. So I’d do the following, for an imaginary plugin I’ll call awesome-plugin:
    [bash]
    cd /sites/doris/wp-content/plugins
    mkdir awesome-plugin
    [/bash]
  3. Before connecting to WP SVN, it’s a good idea to check for the revision number of your most recent commit. If you don’t, git-svn will sift through all 280,000+ revisions on svn.wp-plugins.org.
    [bash]
    svn log http://svn.wp-plugins.org/awesome-plugin
    [/bash]
    Scroll to find the most recent reversion number. Let’s say that in this case it’s r287228.
  4. Clone the svn repository to your newly created directory. Because I want this working copy to actually work as a WordPress plugin, I’m not going to check out the entire awesome-plugin tree. Instead, I’ll just get the trunk, and when I want to tag new versions of the plugin, I’ll do it in a separate working copy on my machine. (This is perhaps not the ideal way to work, but for me it works – probably irrationally, I like having “clean” instances of the trees somewhere on my machine that are used only for tagging new versions.)
    [bash]
    git svn clone http://svn.wp-plugins.org/awesome-plugin/trunk awesome-plugin -r287228
    [/bash]
    git svn clone will create the git-svn link and then do the initial fetch into the awesome-plugin directory.
  5. Depending on how you’re planning to use Git, you might want to create a branch that tracks the svn trunk, just for stable svn releases:
    [bash]
    cd awesome-plugin
    git checkout -b svn remotes/git-svn
    [/bash]
  6. Now that we’ve connected Git to WP SVN, we can connect to Github:
    [bash]
    git remote add -f origin git@github.com:boonebgorges/awesome-plugin.git
    [/bash]
    I’m calling Github ‘origin’ because I’m so used to push and pulling to and from ‘origin’, but you can call it whatever you want. Of course, make sure to change ‘boonebgorges/awesome-plugin.git’ to reflect your username and repo name.
  7. Let’s test the connections. If your Github repo is empty, you can push stuff up right away:
    [bash]
    git push origin svn
    [/bash]
    Remember that I am working on a branch called ‘svn’; you might use ‘master’ or something else altogether if you’d prefer. If your Github repo already had some files in it, you might find that you have to pull and merge them before pushing. Now make a change to your local:
    [bash]
    touch test.txt
    nano test.txt # Type something in the document and save it
    git add .
    git commit -m "testing git-svn"
    git push origin svn
    [/bash]
  8. Finally, let’s test to make sure that we can commit to SVN.
    [bash]
    git svn dcommit
    [/bash]
    The first time you try this, you will be prompted for your wordpress.org password. If your local username is not the same as your wordpress.org username (mine isn’t), just hit enter and SVN will ask for your full creds. You should get a “Committing to…” message, followed by “Committed r123456” or something along those lines. You can check to see that your commit has gone through by visiting http://svn.wp-plugins.org/awesome-plugin/trunk in your browser.

Good luck!

New WordPress plugin: Simple Import Users

My palz Mikhail and Luke over at Blogs@Baruch needed an easier way to add users to sites in the WordPress network. They’d been using DDImportUsers, which worked, but was finicky: DDIU required you to specify too much information, its formatting was tough for instructors to understand, and, most importantly, it didn’t deal well with existing accounts, which it simply ignored instead of adding as new users to the site in question. So they asked me to modify the plugin for their purposes.

The result is a near-complete rewrite, released today under the name Simple Import Users. Instead of entering all sorts of information about username, password, display names, etc, Simple Import Users accepts only a single argument: email address. That makes it simple enough for anyone to use. Insert a list of email addresses into Simple Import Users, and it checks each email address in the following way:

  • If a WP user is *not* found with the email address in question, SIU creates a new user with that address. The username is automatically generated from the part of the email address before the @-sign, which means that this plugin will probably work best for those setups where you can guarantee unique email prefixes (like schools). Passwords are randomly generated.
  • Then the new user (or the existing user, if one was found) is added to the blog.
  • The user is then sent a customized welcome email. All users get a message saying that they’ve been added to the blog, with information on how to access the dashboard. In the case of new users, it contains their login info as well.
  • If you’re running BuddyPress, the email to new users also contains a message encouraging users to fill out their BP profiles, with a link to the Edit Profile page.

The plugin has no settings, and is intended for this very specific purpose. But if you’ve got a setup like Blogs@Baruch, it could save you a lot of time and effort.

Get the Simple Import Users here.