Let’s talk about the WordPress Registration Process.
So, the little tidbit (or intro post – whatever you want to call it) in making Membership sites that I posted a little bit ago was apparently a “tantalizer.” People are wanting to know more… more “meat” I guess you could say. It’s funny, so far, this year “membership” sites, or “restricted access” sites are pretty much all I’ve done this year (and the end of last) so I’m getting more and more into it.
Now, I haven’t used a lot of stuff when it comes to doing the whole registration process – which is a big thing for membership sites of any kind. I know how to create my own forms – and I did, for a loooooong time, because I couldn’t find a form plugin that I liked well enough (because – as always – I was restricted to what the plugin author thought I should have it as, instead of what I wanted). So I can say that you can create a custom registration form script for your WordPress site from scratch. But it’s NOT EASY. In fact, it tends to lean to the “migraine inducing nightmare” end of things. This is why, aside form my own custom code, I’ve switched to Gravity Forms.
Now, please understand, I’m not an affiliate in any way shape or form of the plugin. I just love it. Love to use it, so glad I found it, blah blah blah. I recommend it to everyone. It just makes life so much easier.
The problem with Gravity Forms is, if you want to use the Registration Add-On and/or the PayPal Add-On, you have to buy a developer’s license. And unless you’re a developer, well… that’s a nice chunk of change out of pocket. As a developer, it’s totally worth it. But if you’re interested in getting Gravity Forms for your one membership site (that you plan to handle on your own) it’s probably not an option for you.
Unfortunately, because these are the only two options I’ve used, I can’t really comment on other methods. I know there are plugins out there that will allow you to customize registration, and some that will allow users to register and be created (and wait for manual approval before gaining access), but I have no recommendations or opinions on those. I think it would be unfair of me to even try.
So the sad news is, this tutorial is a bit one-sided, since it’ll focus on the use of Gravity Forms. (I’ve actually rewritten this post 4 times already, because I seriously considered making it one to show you how to do it from scratch, but when I say it’s a headache to do it, I’m not kidding. If there’s enough interest, then I may show how it’s done in the future, but I’ll only do it if people really REALLY want to know.)
The problems.
There are several problems with Membership sites that people have trouble solving. in the registration process alone, there’s quite a few. So I’ll go over them quickly.
- Creating an actual form that has a ton of info not natively handled by WordPress – how do you take the info from the form and save it to be handled later on?
- What do you do when you want to have paid membership registrations?
- If the form handles the info and creates a user, how do you prevent the user from gaining access before they’ve been approved?
- Even if you can do the above, how do you prevent end users from bypassing your setup (i.e. manually typing in the wp-admin or wp-login URLs in the address bar and just clicking “lost password?” to issue themselves a password.)
- In relation to the above, how do you “hide” the back-end from non-administrators?
So most of the issues above can be addressed by using Gravity Forms and the User Registration Add-On (and the PayPal Add-On, if you want paid memberships). But as I said before, you can handle the rest of the issues by combining this with the Theme My Login plugin. These are really the only two plugins you need. (Another plugin you might be interested in is User Messages – but I’ll cover that some other time.)
Gravity Forms
Now this is just a simple overview. I got all excited when I discovered exactly how awesome Gravity Forms is when it comes to customization – there’s so much stuff you can do with it. But this is just a quick overview of a Membership Registration process, so I don’t want to get too far off-tangent. I’ll cover the other goodies in another post some other time.
But Gravity Forms is dead-easy – it’s all drag-and-drop. Create your fields, build your form, and save it. Once you’ve saved your registration form, you want to navigate to “Forms > User Registration.” Then you “map” the fields you created in the form to WordPress’ default fields. Any extra fields you have (that WordPress doesn’t have natively) you simply create a custom field for it (give it a good name, with underscores and no spaces) and it’ll save them all as an array in the usermeta table, which you can pull out later with some custom WordPress functions.
You’ll also want to be sure you uncheck “Send Password to User” (in Gravity Forms – but you want your WordPress site settings at “anyone can register”) if you want to have admin approval for each person that registers – that’ll give you the option if setting the registration default to “pending.” This is important, because if you don’t do this, then the end user can bypass user approval by simply clicking “Lost Password?” and it’ll email one to them. Having the new registrant set as “pending” creates the user without giving them a password, and filling in the “Lost Password” field will result in nothing happening until you’ve actually approved the user. When you do that, you simply go to their profile page, change their user level, and supply a password. (With my clients, I simply have them do that, then email the end user that they’ve been approved, and pass them the link to the “Lost Password?” field so they can create a password themselves. I also find it very useful to add the Better WP Security plugin to sites, because this plugin can force the end user to create a strong password, instead of something lame and easy to hack.)
Using Theme My Login
I’ll tell you in another post how to use the registration information once you’ve got it – that dives into some other stuff. Since we’re focusing on the registration process itself, I’ll tell you how to set it up so you don’t get any weird users who have managed to bypass your pretty registration form.
The Theme My Login plugin does a great job of this (doesn’t cover 100% of the issues, but it sure does take care of about 99.9% of them!). When you install and activate the plugin, go to the settings and first, attack the modules. The ones I always use are: Enable Custom Redirection, Enable Security, Enable Themed Profiles, and Enable User Moderation.
The Redirection part is what’s really nice. You can go through each user level, and set what you want to have happen when the end user logs in and logs out. I leave “Administrator” at “default”, which means when they log in, they’re taken directly to the dashboard in the back-end, and when they log out, they’re taken to the “log in” page.
For all other levels, I set them to the same thing for both log in and log out: “referer”. This way, no matter what page they are at when they decide to log in (or log out) the site will return them to that page once they’ve performed the desired action. I had one client that liked the end user to be returned to the home page when they logged out, so that’s an option as well – just put the URL you want them redirected to in the input box (the last choice).
Security doesn’t really have much to do with registration, other than locking someone out when they’ve tried to bully themselves in. If you have Better WP Security installed and activated, you really don’t need this, but the option is nice.
Moderation is just another level of making sure that the end user does NOT get a password (and therefore access) until you, the administrator, has approved the user.
Themed Profiles is nice, as well – because it allows the (approved) end user to go in and edit their profile without ever seeing the back end of WordPress. Since the “member” is usually a subscriber, there’s really no need for them to ever have access to the back-end anyway, so it’s a really nice touch.
This plugin also allows you to edit the template files for it easily: simply find the template file you want to edit, copy it, and save it (with the same name) in your own theme. The plugin will look for the template in your theme first, and revert to the plugin default if one isn’t found – which is very similar to how WordPress theme files work.
I tend to open up the login-form.php, lostpassword-form.php and profile-form.php files and do my magic there. I will change the “Register” link to point to the Gravity Forms registration page I created (so any time anyone clicks “register” it’ll take them to the proper registration form – if you don’t change it here, it’ll take you to the WordPress default registration page, and we don’t want that!)
Theme My Login does a terrific job of redirecting anyone who wants to log in to the proper non-WP back end page, but those little links in the bottom WILL take you to the default WP area unless you change that “register” link to point to your Gravity Forms registration page. But the plugin still will not stop people from manually typing in the address and accessing it. To stop it, all you need to do is add this teensy code snippet to your functions.php file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
add_action('init','possibly_redirect');
function possibly_redirect() {
$thispage = $_SERVER['REQUEST_URI'];
$register = site_url('/register');
if(strpos($thispage, 'action=register') !== FALSE) {
wp_redirect($register);
exit();
}
}
What this does is look for “action=register” in the URL (because you can pretty much take ANY url in the WordPress site, add “action=register” to it, and it’ll take you to the registration page) and if it’s found in the manually-typed URL, it’ll redirect the end user to the page set for $register.
Problem solved.
You’ve now set up your custom registration form, for manual admin approval, and kept the bad guys from getting in when they should not.
Paid Memberships
So the only question left to solve is “what about paid memberships?” The answer is, again, Gravity Forms, using the PayPal Add-On. However, there’s something a little more important than just “how to”… it’s “what’s your process?”
Now, one client I did this for had a process for paid memberships that I didn’t like – but that’s just me. I tend to think about the end user experience a lot. What they did was have the end user fill out a form, and it would redirect them to PayPal, where they would pay for their membership, and then wait to hear if they were approved. I thought that was a weird process – because what if they weren’t? What if the approval was rejected? They’d have to wait for a refund, and then who eats the PayPal fees? It seemed lik a bad idea for the business to eat the fees – they get nothing out of it and are losing money, and it’s not fair for the end user to eat them, because they paid on good faith. (I found out later that if a refund is issued, there are no fees – but I didn’t know that at the time.)
But that was the process that worked for them, and apparently no one but me has complained yet! So definitely think about what your process for paid memberships will be. Do you want the end user to pay upon registration submission? If so, will they be given instant access? or will you want approval first? Will you issue a full refund if you reject them? Or, would you rather review the registration, and then send them an invoice at a later time to have them pay for their approved membership, and have the password stuff sent to them after they’ve paid?
It all makes a difference in how you set up the Add-On (or if you set it up at all! If you choose the last option, you probably don’t need it!)
So hopefully that helped a bit – giving more insight into the whole custom registration process. I’m sure – if you decide not to use Gravity Forms – that there are other registration options out there. Just, like I said, I’ve never used them, so I don’t think it’s fair for me to comment on them. But there’s a few tidbits up there that I think will be useful for any custom registration process.
Soon I’ll be posting some other goodies on the whole “Membership” process and some of the stuff I’ve worked on – and hopefully that will help, too!
WordPress and Memberships
Oh, this was something I was going to save for my redesign. I’m about 98% finished with my website redesign (which is SO BADLY needed – but you know the whole thing about cobbler’s children and all), and this tutorial was going to be one of the first new items I put on the blog. However, I’ve found myself, over the last couple of weeks, hearing the same question asked over and over again (with different words of course – they think they are asking a different question, but they aren’t) and me answering it the same way over and over again.
As to this one point, I do not blame anyone for asking the same question over and over again,because I can understand how they think their situation is different. So hopefully no one thinks I’m a big, fat meanie that’s “venting about complainers” or something – because I’m totally not. I’m just tired of typing the same answer a lot, so I figured I’d put it one spot so I can just link to it and save my fingers from cramping!
Okay, so the question is this: “What’s the best plugin for turning WordPress into a membership directory?” (or another variation: “How to do keep [insert some page or file name here] from being accessed by people who shouldn’t have it?” There’s many more variations, but I think you get the idea.)
It’s actually a LOT easier than you think, and it really doesn’t require an extra plugin. Don’t get me wrong, an extra plugin will help (especially with more advanced variations on the theme), but it’s not necessary. Really, you just need one single function that is actually already a standard part of WordPress core: is_user_logged_in().
Basic Form
Now, your most basic requirement would be to, say, keep a section of your site from being viewed or indexed by Google. Be it a single post, or Page, or an entire section (like a whole category, or custom post type, or a set of Pages – what have you): the above function is pretty much all you need. Most people’s first line of thought is to make a Page or a post, and then password-protect it.
That’s fine, but there’s a big problem with this: you have to add a password to each individual Page or post you want to do this to. So if you password-protect several Pages, that means when someone goes to view it, they have to enter in a password for every. Single. Page. (A second quasi-issue is, you have to remember the password. WordPress doesn’t provide a way to “remember” or show passwords you’ve set on posts, so if you forget, you have to reset the password – then everyone who has it saved has to re-save them again.) So annoying. End user experience: shot.
There’s so many other ways to accomplish it, too, but if you already know what section it is that you want to have “protected”, and you know no more sections will be added to it, you can simply add the above function to your theme file (index.php or content.php – whatever it’s named that actually pulls in the content). Basically, you just want to find <?php the_content(); ?> and replace it with this:
1 2 3 4 5 6 7
<?php
if(is_page('Some Page Name Here') && is_user_logged_in() == TRUE) the_content();
else echo "You must be logged in to view this page.";
?>
That’s pretty much the simplest form of doing it right there. Basically it checks to see if the user is logged in, and if they are, it’ll show the content, if not it’ll tell you that you need to log in. BAM. Done.
You can use this function with current_user_can() and even associate content with the user level as well, for, say, doing “tiered membership levels”.
Of course there’s TONS of variations on this theme. For example, if you’d like to dynamically adjust what’s seen and what isn’t (i.e. there’s posts or Pages in the future where you’d like them to be hidden), you could do something as simple as adding a custom field (or a category, or a custom post type) that you can check a box to keep it hidden, and have the theme look for that flag. An example of this:
1 2 3 4 5 6 7 8 9
<?php
$members_only = get_post_meta($post->ID, 'members', TRUE);
if($members_only == 'yes' && is_user_logged_in() == TRUE) the_content();
else echo "You must be logged in to view this page.";
?>
This is such a cool process because it negates the need for password-protected pages and stuff – you no longer need that extra step. If someone’s logged in, they see it – if they aren’t, they won’t.
Now I just did a site where there was full-on paid membership requirements for the WordPress site. This is the part where you could roll your own code (and believe me, I have before – and I can tell you how, but that’ll be a tutorial all on its own for another day), but why reinvent the wheel, right? What I did was simply use two additional plugins: Gravity Forms and Theme My Login.
Note that Gravity Forms is not free – but I tell you it’s worth the price, ten times over. And no, I have no affiliation with them to try and sell it to you. Buy it or not, I don’t care – I get nothing either way. But I’m extremely happy with them, and I recommend them highly!
Theme My Login isn’t required, but I’ll tell you why (later) it’s a nice addition that will solve some issues that will crop up.
Gravity Forms
The reason I like Gravity Forms is because you can easily create a really customized form – it’s DEAD easy. Drag-and-drop, baby. It even allows you to roll up your sleeves and add some customizations to it that require coding and filters, if you are so inclined. So if you’re running a membership site that requires the applicant to, say, provide an address and phone number, you can use Gravity Forms and the Registration Add-On and you’ve got yourself a full-on membership plugin. (You can also use Gravity Forms as a paid membership plugin, using the above add on as well as the PayPal Add On, but you have to have a developer’s license for the PayPal addition, which may be out of the price range of some people. But since most people that read my stuff are developers, then that probably isn’t the issue. You’ll make your money back hand over fist.)
I’m not going to do a step-by-step on how to use Gravity Forms and the Registration Add On (because there’s already tons of that out there – you basically just create the form and map it to user fields – I don’t need to add another tutorial to the saturated list.) But once you get the form created and mapped, you’re set to have members go to that page and apply to join up. The information from the fields is mapped to some of the WordPress profile defaults and the rest is popped into the usermeta table (so you can access it later, say, for a member profile page).
I’m going to put in a note here: a lot of people like “membership directories” as well. Gravity Forms has a “directory add on” that’s available – it’s something someone created to work with Gravity Forms, but it’s not developed or handled by the Gravity Forms people itself. I tried it, initially, and it works pretty nicely. But if you want a customized directory (or one that shows more information the higher you go up the user level chain) it’s not a good solution. I have nothing against the Add-On itself, it really does work as advertised, but when I needed to get it customized to suit the project I was working on, I ended up coding out my own. (Hey! another tutorial for later!)
Now, you could stop there. But there is an issue that will happen if you do: the default WordPress login page will still exist, and people can still have access to it if they know where it is. Considering “allow registrations” must be activated to…you know…allow people to register, that means if someone knows where the default login form is, they can manually type in that address, bypass your sweet form, sign up and done. They’ve bypassed everything, and become a member without your approval.
This is where Theme MyLogin comes in handy. You can set this plugin up and it’ll take over, and it’ll format your login page to look exactly like the front end of your site. You can set it so, when someone logs in, they will never, ever, ever see the back end – not even to edit their profile page (if you activate the “Theme My Profile” portion of the plugin). In the site I did, I had this setup for everyone except administrators – they would redirect to the back-end of WordPress if they were logged in. All other user levels would redirect to the page they were at before they logged in.
Using the two plugins together really makes for a nice “membership” website that really is simple to create. (Add on Events Manager and you can have events for members and public events that people can pay for tickets and RSVP to as well! Again, no affiliation – just like it.)
Downloadable Files
Another issue is that some people simply want to keep a file download private. This is a bit more difficult than just restricting Page/post content. If someone actually does access the file (legitimately) and they link to it from somewhere, there’s nothing to stop them from directly linking to the file itself, since they know the URL. And if it’s emailed – especially through a gmail account – fahgeddaboudit. Google will index it (Gmail = Google – yet another reason to not send passwords and login info/sensitive data through email!), and next thing you know it’s showing up in Google search.
So what do you do?
There are different solutions (as far as file downloads go). Now, you can find a plugin that will protect these files – I know a lot of people who like LinkLok. There’s also a few plugins in the repository that look promising. But you can also do a couple of things yourself if you like (and don’t want to depend on a plugin). One thing is to place the images above the public root of your directory (with some hosts, the public directory is “www” or “public_html”) – when you do that, people can’t link directly to it (or type in a URL to access the file) since it’s a level above public access. Then you can create your own method of allowing permitted users to access the file by using a bit of PHP code. Now, this method requires that you FTP into our server to upload the files you want to add, which is one option. But you can also create a little admin page for yourself where you can upload this stuff and handle it through the WordPress back-end, and it stays out of your Media stuff (it’s all nice and compact, in one spot, away from all the other stuff.) – which actually…
I’m so bad! I thought I’d published that as a tutorial some time ago, but I guess I’m wrong! So I suppose I have something new to write about at a later date!
In any case, using a plugin (or adding something like LinkLok to your site would help alleviate the issue of keeping downloadable files secured
It really is that easy.
You don’t need to go purchase big membership plugins, or pay out the nose to make some content visible to some while hidden from others. It’s already built in to WordPress to allow that to happen. With just a couple of extra additions, you’ve got yourself a nice little membership site with everything you need
Hopefully this will be a help to someone!
And yes, I swear I’ll put up the other promised tutorials – but really, don’t make me do it until I get my redesign finished!
wp_logout_url()…. AGH!!!
So I’m working on a site right now that incorporates the new bbPress plugin with WordPress. I’m testing the login/logout process, and since it’s now a plugin (instead of a standalone) you can use your WordPress logging for both things (the site and the forum).
So I’m putting in a link for the logout url, via wp_logout_url(), and I’m following the Codex instructions for the redirect. but as I continue testing, I realize that the redirect isn’t working. Hmm. So off to the forums I trot.
And discover that this isn’t a new issue.
So I start picking things apart. After a gazillion times of logging in and out, I realize a single weird thing: when I log out, it’s adding in a new directory. So this is why none of my code is working, and why it keeps going to a 404 page. (Let me ‘splain, Lucy.)
The site url is http://localhost:8888/somesite.
When I log out – well first off, it’s completely ignoring the redirect, and redirecting to the page you’re already on. Doesn’t matter if you’re using get_bloginfo(‘home’); or home_url(), or site_url() in there – even if you hand-code the home URL (or any other URL for that matter) in there, it’s ignored. What it ends up doing is, when you log out, the URL it redirects to is this (assuming the page you’re on when you log out is “somepage”):
The site url is http://localhost:8888/somesite/somesite/somepage?loggedout=true
It took me a few times to realize that “somesite” was being put in there twice. Well no freaking wonder it wasn’t working.
So of course I did what I always do. I could have put in a hack and hard-coded the link (or other methods), but the wp_nonce_url would not be there, and I’m a safety gal. So after about 20 minutes of logging in and logging out after each code tweak, I found a solution.
I present it to you.
The original function in WordPress core (in wp-includes/general-template.php) is like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
function wp_logout_url($redirect = '') {
$args = array( 'action' => 'logout' );
if ( !empty($redirect) ) {
$args['redirect_to'] = urlencode( $redirect );
}
$logout_url = add_query_arg($args, site_url('wp-login.php', 'login'));
$logout_url = wp_nonce_url( $logout_url, 'log-out' );
return apply_filters('logout_url', $logout_url, $redirect);
}
After major tweaking, I found that the last line is causing the problem. Remove it, and pop it outside the function, and it works like it’s supposed to. So if core were like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
apply_filters('logout_url', 'wp_logout_url')
function wp_logout_url($redirect = '') {
$args = array( 'action' => 'logout' );
if ( !empty($redirect) ) {
$args['redirect_to'] = urlencode( $redirect );
}
$logout_url = add_query_arg($args, site_url('wp-login.php', 'login'));
$logout_url = wp_nonce_url( $logout_url, 'log-out' );
return $logout_url;
}
it works a treat.
Now I’m never one to recommend editing core. Never never never. But when you have an issue like this, you can basically just do it anew in your functions.php file (within your theme), and if the WP devs fix it (or not) you never have to worry about losing the fix. So if you rename the function above and pop it into your functions.php file, then you’ll be all set. i.e.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
apply_filters('logout_url', 'my_fixed_wp_logout_url')
function my_fixed_wp_logout_url($redirect = '') {
$args = array( 'action' => 'logout' );
if ( !empty($redirect) ) {
$args['redirect_to'] = urlencode( $redirect );
}
$logout_url = add_query_arg($args, site_url('wp-login.php', 'login'));
$logout_url = wp_nonce_url( $logout_url, 'log-out' );
return $logout_url;
}
Then, wherever you were planning to use wp_logout_url(), use my_fixed_wp_logout_url() instead. Yay!
WordPress Plugin Repository
So a looooong time ago, I released my first WordPress plugin – expandable jQuery comment replies. I’ve been remiss in keeping it updated – it was written for WP 2.7, and here we are, almost on 3.1. So when I released by Back End Instructions plugin, I decided perhaps I should be a good girl and update my old plugin.
Updating it locally wasn’t an issue. however, updating the repository…. that’s a different story.
I don’t use Terminal a lot, so it’s still a little bit alien to me. I’m not terrified of it anymore, but I still walk on eggshells when I use it – I don’t want to ruin anything. (My stuff, I don’t care so much about – it’s accidentally…I dunno – wiping out the entire plugins database that scares me! LOL) Although the first time I added a plugin wasn’t so difficult, like I said – it’s been a while, updating is another story.
There’s a nice codex page on the issue, but it doesn’t really dive into the whole thing. I think it was written more for people who are used to downloading the nightlies, and adding code and plugins like crazy all the time. The Codex page is more of a “quick overview” kind of thing.
So while it’s fresh in my mind, I’m going to share a few little tidbits that I’ve come to understand – so when I do this again I don’t have to spend three hours just trying to update something.
Adding a brand-spanking new plugin
First off – when you want to add a fresh, new plugin, you have to ask first. I don’t remember doing this before, so it must be a new thing they’ve added to help maintain quality control (which is a good thing). From what I’m reading, when you submit the form for adding a plugin, you’re basically notifying the WP team that you want to add a new plugin, and apparently they download your file and take a few days to actually check it out (I’m being told it’s anywhere between 3 to 10 days – for me it was pretty quick). Then they’ll send you an email and give you your SVN directory so you can add the files to the repository.
Once you get the go-ahead to submit the plugin, you need to shell into the system to add it.
Now, again, I use Terminal. I’m on a Mac, and it comes with this sweet little program already built in. I don’t know what you’d use for a PC, but I do recall needing to shell some stuff back when I was using one, and I had to find and download a program – my system didn’t had anything built in for it. (Again, this is based on an old lady’s memory.) So if you’re on a PC, you’ll have to find something that allows you to shell into the plugins server. The following instructions are Mac-based, but I believe shell access doesn’t care if you’re on a Mac or PC, so if you’ve got something that gives you access, these instructions should work for you.
So, using terminal, you basically open up the puppy, and you should be in your root directory (Macintosh HD/Users/your computer name). It’ll basically look – in the Terminal Window – like:
192: ~ somename$
and have a little square cursor next to it.
Now, you want to create a new directory to store all your stuff in. So you type in (for purposes of example, we’ll use the name “plugins”)
mkdir plugins
and hit “enter.” If you have a Finder window open, you’ll see a new directory being created there
Now you need to access your own little part of the Repository world. The directory name they gave you (we’ll say it’s “love-potion-9″ in acknowledgement of Valentine’s Day) is your address. So next, you need to type in:
svn co http://svn.wp-plugins.org/love-potion-9 plugins
And this basically “checks out” what is there. If this is a new plugin, most likely there won’t be anything but some empty folders (trunk/trunk, branches, tags), and everything in your little area will be downloaded to your new plugins” directory.
So now you want to copy the plugin files you have on your computer to the “trunk” directory of the stuff the SVN just added to your hard drive. DO NOT create a subdirectory, and DO NOT put in a zipped file. Just take all the files from the root level of your plugin and move them to the “trunk” of the new area.
Now, back to Terminal. You need to “speak” to the WP server and tell it you’re preparing to commit some stuff to the server. You have to let it know that there’s new stuff there. So you need to change the directory to your local plugin area
cd plugins/
and then you should see the beginning part change – instead of
192: ~ somename$
you should see
192: plugins somename$
that’ll tell you you’re in the right directory. (if you get an error that the directory doesn’t exist, type in cdand it should move up a level, then try again.)
Now you want to “speak” to the repository, and tell it to take the files that are in your local copy and copy them to the matching directory in the WordPress repository. You do this by typing in:
svn add trunk/*
This basically tells WP that you are in your “plugins” directory that matches theirs, and you want to take everything in your local “trunk” directory and copy it to the WordPress’ matching “trunk” directory. You’ll see the terminal window sort of pause for a few seconds, then this stuff will show up. The lines will begin with “A” (the WP server telling you it’s “added” the files) and then the curosr will appear again.
Once you’re satisfied that all the files are properly in their place, you want to commit this. (If you quit now, then everything you’ve done up to this point will go away.) So you type in:
svn ci -m 'Adding first version of my plugin'
And you’ll see a message that the files are transmitting, and finally it’ll give you a “committed revision” message. All done – you can close out. Usually, in no more than 15 minutes after this point – the new plugin will show up is the plugins repository. You can easily see it by looking at the “Newest” section. By the way, the “Adding first version of my plugin” thing can really be any message you want to have there.
Updating an existing plugin
This is where I ran into trouble – apparently adding is much easier than editing! (Well, not really, but it seemed like it LOL). Really, it’s very similar to adding a new plugin. You want to start by opening up Terminal, and making sure you’re in whatever directory you want on your hard drive (I like to do my stuff at the very root of my hard drive, so I don’t accidentally edit it at some point in the future) and log into the repository to “check out” the file system that’s living there, again by typing in:
svn co http://svn.wp-plugins.org/love-potion-9 plugins
NOTE: be aware that when you do this, if you’re in your local copy, it’ll overwrite what’s there. So if you’ve already made changes, I HIGHLY recommend that you rename your existing “trunk” folder to “trunkNEW” or something so your changes don’t get overwritten, and then move the files after you’ve checked out what’s on the WP server, so you don’t lose your changes.
This will basically copy the files in the repository to your hard drive (“checking out” – like at the library). You can then open up whatever files you want to edit (I HIGHLY recommend the readme.txt file and the root file so you can change the version number and add to your changelog. But the readme.txt file is the big one.) Once you’ve made your changes, simply save them, and change your directory in the terminal so you’re in your plugin area (if you haven’t already) and then type in:
snc ci -m 'Updating my plugin to version whatever'
and hit enter. it magically knows which files you’ve changed – you’ll see them list up and it’ll end with “Committed revision [some number]“. In a bit, you’ll see the version number of your plugin in the plugins area of WordPress.org change to the new version, and everyone will be magically alerted to the update.
Better Text Widget
NOTE: October 5, 2010
I just recently used this plugin while developing locally for a client. I did an SQL export of the site to move the testbed to the live server, and was muchly surprised to discover this widget does not get retained in the database for some reason. I had to redo all of the widgets manually.I just wanted to post notice of this bug, because I want you to know that I know, and I’m working to correct it.
Yes, I’ve been quiet for a few weeks. I’ve had some issues come up, and have been trying to knock them out of the park. I was just saying this morning, it amazes me how I’m on sabbatical, but I’m busier now than I was when I wasn’t! (OMG – that has to be some kind of grammatical nightmare right there.)
Anyway, recently I’ve had a lot of people around me (not directly to me, but sort of discussing around me) that they are using WordPress, but wished they’d had a widget that would pull off certain functionality. I can’t give you their exact words, but the gist of it is that they want some kind of easier-to-use text widget.

If you don’t know what I mean, basically WordPress has a default widget (that comes with the installation) that’s called “Text Widget”. The description of said widget is “Arbitrary text or HTML” So basically you can type up any text you want and shove it into a Widget. If you know a little HTML, you can put in an image, etc., but you would have to know the proper syntax to do it. Most of my clients look at HTML as if it’s Mandarin Chinese. However, using other widgets are overkill, and sometimes present “TMI” that they can’t seem to sort through. What they wanted was a Widget where they could put in text (or even just have an excerpt from a particular page or post), easily add an image, and even have the title of said widget look different than the title they name the widget.

Lucky for you all, I’ve already written one, and have been using it for some time. Over the last 3 weeks (or so) I’ve been handing out the code for it when anyone asks me for it. I was just getting ready to send it again, when it just dawned on my that DUH – that’s what my site is for. So here. Take it! Just pop this code into your functions.php file, and run
Update on July 12, 2010: I’ve been asked also to add in something to make the title of the widget be optionally hidden. It just so happens that I just finished doing exactly that for a client recently, so I’m adding in those lines.
Also – not because I was asked, but because I’ve found this addition very handy – is the option to make accessing the theme directory files easier. Many times, I’m developing on my own server and eventually I need to move the site to a client’s server. Many of the widgets have a full path coded, and those don’t change when you move the site, so stuff ends up broken. I’ve edited the code to make that a whole lot easier.)
$home = get_bloginfo('home');
$templatedir = get_bloginfo('template_url');
$uploadsdir = wp_upload_dir();
$uploadsdir = $uploadsdir['baseurl'];
$imgdir = $templatedir . '/images'; // be sure to change the directory to whatever you've named your images directory within your themes folder
add_action( 'widgets_init', 'easier_text_widgets' );
function easier_text_widgets() {
register_widget( 'Easier_Text_Widget' );
}
class Easier_Text_Widget extends WP_Widget {
function Easier_Text_Widget() {
$widget_ops = array( 'classname' => 'easier_text_widget', 'description' => __('Similar to the plain-vanilla "Text", but makes it easier to manipulate without the need to know PHP or HTML.', 'easier_text_widget') );
$control_ops = array( 'width' => 300, 'height' => 350, 'id_base' => 'easier-widget' );
$this->WP_Widget( 'easier-widget', __('Easier Text Widget', 'easier_text'), $widget_ops, $control_ops );
}
function widget( $args, $instance ) {
global $post, $imgdir, $uploadsdir, $templatedir, $home;
extract( $args );
$title = apply_filters('widget_title', $instance['title'] );
$hide = $instance['hide'];
$image = $instance['image'];
$link = $instance['link'];
$link_text = $instance['link_text'];
$id = $instance['id'];
$text = $instance['text'];
// replace "home" with home url
$findimg = strpos($image, 'images');
$findhome = strpos($link, 'home');
$finduploads = strpos($image, 'uploads');
$findlinkuploads = strpos($image, 'uploads');
if($findimg !== false) $image = str_replace('images', $imgdir, $image);
if($finduploads !== false) $image = str_replace('uploads', $uploadsdir, $image);
if($findhome !== false) $link = str_replace('home', $home, $link);
if($findlinkuploads !== false) $link = str_replace('uploads', $uploadsdir, $link);
if($hide !== false) $class = 'class="hideme"';
else $class = '';
echo $before_widget;
if (!empty($link) && empty($image) && empty($link_text)) {
echo $before_title . '<a style="font-size:1.1em;" ' . $class . ' href="' . $link . '">';
if (!empty($title))
echo $title;
echo '</a>' . $after_title;
} else if(!empty($title)) {
if($class == '') echo $before_title . $title . $after_title;
}
if (!empty($image))
$img = '<img src="' . $image . '" alt="' . $link_text . '" />';
if (!empty($link)) {
echo '<a href="' . $link . '">';
if(!empty($image))
echo $img;
else if(!empty($link_text))
echo $link_text;
echo '</a>';
} else if(!empty($image)) {
echo $img;
}
if (!empty($id)) {
$excerpt = get_the_excerpt();
if($excerpt == '') {
$excerpt = get_post_meta($id, 'page_excerpt_value', true); // post meta value
}
echo '<p>' . $excerpt;
echo '<a class="more-link" href="' . get_permalink($id) . '"> more</a></p>';
}
if (!empty($text)) {
$findimg = strpos($text, 'images');
$findhome = strpos ($text, 'home');
$finduploads = strpos($text, 'uploads');
if($findimg !== false) $text = str_replace('images', $imgdir, $text);
if($findhome !== false) $text = str_replace('home', $home, $text);
if($finduploads !== false) $text = str_replace('uploads', $uploadsdir, $text);
apply_filters( 'widget_text', $instance['text'] );
echo $instance['filter'] ? wpautop($text) : $text;
}
echo $after_widget;
}
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title'] );
$instance['hide'] = isset($new_instance['hide']);
$instance['image'] = strip_tags($new_instance['image']);
$instance['link'] = strip_tags($new_instance['link']);
$instance['link_text'] = strip_tags($new_instance['link_text']);
$instance['id'] = strip_tags($new_instance['id']);
//$instance['$text'] = stripslashes($new_instance['text']);
if ( current_user_can('unfiltered_html') )
$instance['text'] = $new_instance['text'];
else
$instance['text'] = wp_filter_post_kses( $new_instance['text'] );
$instance['filter'] = isset($new_instance['filter']);
return $instance;
}
function form( $instance ) {
global $imgdir, $uploadsdir, $templatedir, $home;
$defaults = array( 'title' => __('', 'easier_text'),
'hide' => __('', 'easier_text'),
'image' => __('', 'easier_text') ,
'link' => __('', 'easier_text'),
'link_text' => __('', 'easier_text'),
'id' => __('', 'easier_text'),
'text' => __('', 'easier_text')
);
$instance = wp_parse_args( (array) $instance, $defaults ); ?>
<p><label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'hybrid'); ?></label>
<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" style="width:100%;" />
</p>
<p><input type="checkbox" id="<?php echo $this->get_field_id( 'hide' ); ?>" name="<?php echo $this->get_field_name( 'hide' ); ?>" <?php checked($instance['hide']); ?> />
<label for="<?php echo $this->get_field_id( 'hide' ); ?>"><?php _e('Visually hide title'); ?></label>
</p>
<p><small style="color:#777; font-style:italic;display:block;">If you'd like to use an image (that's not already within the content) in this widget, enter in the full path to the image. <br />
Use "<strong>images</strong>" instead of the full path for images located within the theme files. For example, "images/BG.jpg" will convert to "<?php echo $imgdir; ?>/BG.jpg. <br />
Use "<strong>uploads</strong>" for the path to the uploads directory, if using a media file image. This will give you the first part of the directory, but you will need to supply the rest of the path to the file - the year, month directories and image file name.")</small><label for="<?php echo $this->get_field_id( 'image' ); ?>"><?php _e('Image Path:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'image' ); ?>" name="<?php echo $this->get_field_name( 'image' ); ?>" value="<?php echo $instance['image']; ?>" />
<p><label for="<?php echo $this->get_field_id( 'link' ); ?>"><?php _e('Full URL to link image or text to - rules for paths apply as with images:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'link' ); ?>" name="<?php echo $this->get_field_name( 'link' ); ?>" value="<?php echo $instance['link']; ?>"/>
</p>
<p><label for="<?php echo $this->get_field_id( 'link_text' ); ?>"><?php _e('Link text (will also be used as the alternate text for the image):', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'link_text' ); ?>" name="<?php echo $this->get_field_name( 'link_text' ); ?>" value="<?php echo $instance['link_text']; ?>" />
</p>
<p><label for="<?php echo $this->get_field_id( 'id' ); ?>"><?php _e('ID of Page or post you would like the excerpt from:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'id' ); ?>" name="<?php echo $this->get_field_name( 'id' ); ?>" value="<?php echo $instance['id']; ?>" />
</p>
<p><label for="<?php echo $this->get_field_id( 'text' ); ?>"><?php _e('If not using an excerpt, then enter in text you would like to display. HTML is allowed.', ''); ?></label>
<textarea class="widefat" rows="7" cols="20" id="<?php echo $this->get_field_id('text'); ?>" name="<?php echo $this->get_field_name('text'); ?>"><?php echo $instance['text']; ?></textarea>
</p>
<p><input id="<?php echo $this->get_field_id('filter'); ?>" name="<?php echo $this->get_field_name('filter'); ?>" type="checkbox" <?php checked($instance['filter']); ?> /> <label for="<?php echo $this->get_field_id('filter'); ?>"><?php _e('Automatically add paragraphs.'); ?></label></p>
<?php
}
}
Creating an HTML signature file for just about anything
So I’ve recently had the opportunity to create a plethora of (pinatas?) e-mail siggy files
And not just a nice little siggy file to place with your Outlook or Mac Mail program, but in ALL KINDS of things. Even for Gmail.
I had to piece together the “how-to”s from a bunch of different sources throughout the web, but I’m here to share how I did it, and how I managed to make it work for all kinds of different mail-reading-and-sending programs.
read more »
Client instructions through the WordPress admin
So I currently have a client that – no offense to anyone, I swear it – cannot seem to handle instructions to save his life. I’ve written two PDF documents, as well as one in Word format, as well as multiple phone conversations, and having an “Active Collab” type area where your discussions are stored for future reference – and finally emails. However, I still find myself repeatedly giving him instructions, because if it’s not right in front of his face, he forgets (or doesn’t bother to go looking). It is a lesson in frustration, because I’m starting to sound like a broken record to myself.
read more »
Showing Post Titles Within the Category Listing
I had an interesting dilemma over the weekend. Someone sent me a comp to code out (PSD->WordPress), which isn’t anything shocking since I do that a lot. What the dilemma was: in the sidebar, they wanted a category listing. However they wanted only the category listing for the category page you were on. So, say you’re in the “Dogs” category… they wanted the sidebar to have “Dogs” (the current category name) at he top, and have all the child categories listed beneath that. They also wanted it that way on every page: so if you were in “Shih-Tzu”, they wanted the “Dogs” full listing to be in the sidebar.)
Now, this, I’ve done before. No problem. WordPress’ 2.8 system of adding the body class has made my old code moot, and I need to report a new way of pulling this off.
So where’s the dilemma, you ask?
read more »
Setting Up Virtual Hosts on MAMP
Typically I do most of my work on my computer in a localhost environment. Makes for much faster editing – I can change the file on my computer and changes are immediately seen on the “site” locally (the alternative would be edit, upload, wait, reload page, and repeat). Now, on my PC, I used to run a neat little program called XAMPP to put Apache, PHP and MySQL on my computer and turn it into my own personal server. However, now that I’m a Mac user (I switched in early 2008), I use MAMP.
Today, I needed to install WordPress MU to aid in developing a theme for a client. I haven’t used MU in quite some time, and I’d forgotten that it won’t install on simply “localhost” (which is what my current setup is – or rather, was about 20 minutes ago). So, to install WPMU locally, I had to set up a virtual host (i.e. to access my localhost files via “http://localhost.com” instead of “http://localhost”). I discovered that, when using MAMP, it’s sometimes a difficult trial to pull off. I was lucky in finding the info I wanted though – I had it completed in a snap. So, I figured I’d share with you how I did it, so it’s all in one place (and maybe help you!)
read more »
Auto-Create Page associated Widgets
So here’s the idea: I’ve had many clients in the past who wanted to have page-specific widgetized sidebars. Now, I’ve covered this before, but one thing has always gotten me: the fact that you have to write a lot of bloated code to get it to work. It seems like you should be able to pull the post slugs into some kind of array, and have the widgets auto-create themselves with a small bit of code, rather than adding more code every time you add a new page. I’ve com really close to pulling this off in the past, but – as the saying goes – no cigar.
Until now ![]()
read more »
