Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Subdomains, WordPress and nginx

    This should be obvious, but I’m not familiar with nginx, so it wasn’t.

    I added trunk.elftest.net as a separate subdomain (rather than Multisite) because I wanted it to run trunk and not impact anyone else.

    The way that DreamHost works, is you have a separate folder for your nginx configurations, called nginx, and it lives off your home directory. This is commonly referenced as ~/nginx/ and yes, if you type in cd ~/nginx/ you’ll jump right there.

    To make WordPress work, I had to create ~/nginx/trunk.elftest.net and add a wordpress.conf file there, with the standard DreamHost nginx config for WP.

    ######################
     # Permalinks
    if (!-e $request_filename) {
     rewrite ^.*$ /index.php last;
     }

    Magic.

  • Contact Form 7 and Anti-Spam

    DreamHost has a fairly simple anti-spam policy, which can be summed up as this: You cannot send email from an address that isn’t your domain.

    If that was greek to you, don’t worry. What that means is that my WordPress blog here can only send emails as elftest.net. That poses a small problem if you’re not using your domain-name to send email (a rare occurrence in WordPress), and a large one if you happen to be using the popular Contact Form 7 plugin.

    Contact Form 7 lets you create robust contact forms for your site, however it has one minor ‘flaw’ (and I hesitate to use that word). When it sends email, it sends it from the user who submits the form. DreamHost, naturally, doesn’t like this. joe@gmail.com isn’t an elftest user!

    Thankfully there’s a work-around for you, and it’s really easy. For most people, the plugin SMTP Configure, once installed and activated, will automatically fix this for you! It’s written by a reliable and trusted programmer, and I highly recommend it. Remember! Once you install the plugin, just activate it. For the vast majority of people, this was it. Everything magically worked.

    Then there were some people who came and said “No, this does not work.” I’ve yet to reproduce it, but one person told me that after putting in his SMTP credentials, just like you would setting up email clients, it worked perfectly.

    Additional: If you’re using Jetpack’s contact form, and you’ve changed the ‘to’ email address, you will also need this plugin. You’ll know you’re using that option because you’ll see this in your contact form shortcode:

    to="me@myotherdomain.com"
  • Command Line WP

    Command Line WP

    In my new job, there’s a lot of command line work to be done. DreamHost has a mess of scripts I’m getting my comfort with, but also they’ve got this cool thing implemented on a lot of their servers called wp-cli, and that’s what I’m going to talk about today.

    wp-cli is a command line interface to do a lot of sneaky snazzy WP things. While most people are running towards the GUI world of pretty UI and clicks, some of us really like command lines because they’re fast. I mean, I wrote my own command line upgrader just because I wanted to (and was having PHP permissions woes at the time). Command line is just something server people are always going to like, much like people who love driving a stick-shift, or who want to hand-make their own dough for pies. We like to have that extra level on control.

    Aside from being control freaks, however, we CLI jockeys are also insanely lazy. If we can get everything done without having to touch the mouse, or lift our hands from the keyboard, we’re happy. If we can automate things so that all the WordPress installs on a server are magically upgraded in one fell swoop, we’re ecstatic. We all dream of being that guy who walks into a room, presses three keys, and saves the day. (I’ve been that guy, but remember he comes at a cost. I’ve also been the guy who presses three keys and reboots the money trading servers in the middle of our busiest time. Read twice, press enter once.)

    Where wp-cli takes off is in the speed you can perform basic tasks. Typing wp or wp help will get you a list of commands. If you try to run any command outside the WP folders, you’ll get a nice error message. Using Multisite, you have a cool advantage of installing a plugin once and updating it for all your sites. But in cases where you need to have things separated, wp-cli fills the void by letting you script updates. Imagine just writing a simple shell script to upgrade your plugins on all sites?

    Some of you perked up. There are a lot of cases where you don’t want to run Multisite (separate users, special code, whatever), and updating multiple sites under those custom installs really can be a pill. wp core update can be easily scripted to run off a list of your installs, or to just trawl through your directories, look for WP, and update when it’s there.

    Installing

    If you want to install this just on your own account, the directions for installing are on the wp-cli page. But me, I wanted it on my server for all my accounts. Obviously my DreamHost server has it, but this site is still on LiquidWeb (for myriad reasons, one of which is the same as why I didn’t bank at the company where I worked, old habits).

    Their directions are, via git, to install in ~/git/wp-cli, which I don’t want. I decided to put it in /usr/share/wp-cli/ and to do this I just su’d into my root account. Otherwise I could do it all prefacing with sudo, but I’m dangerous like this.

    My first hurdle was the issues I’ve had on git before, simply put the damn thing times out. The fix was so stupidly simple, once I really read into how git works. All I had to do was tell it ‘Use https.’

    git config --global url."https://".insteadOf git://
    

    Suddenly my commands started working and I was able to run the install directions (modified a little):

    git clone --recursive git://github.com/wp-cli/wp-cli.git /usr/share/wp-cli/
    cd /usr/share/wp-cli/
    utils/dev-build
    

    This ran without a hitch. And any update for this, since I’m only ever using trunk, will be as easy as git pull now and then.

    Now on my server, when I try to run certain commands I git this:

    Fatal error: Out of memory (allocated 38797312) (tried to allocate 17 bytes) in /home/userID/public_html/wp-includes/widgets.php on line 635
    

    Two important things to note.

    1. This only happened on one of my accounts.
    2. 37 Megs is a real weird amount of memory.

    I happen to know I usually allocate 64M for my PHP processes, but even bumping this up to 128 didn’t change the fact that at 37M, everything crapped out. I happen to work with one of the leads on wp-cli, and Mike (aka GetSource) let me bounce ideas off him. He offered to help with any questions, but I learn best by doing, so once I sorted out the basics, and was still stumped, I appealed to his greater familiarity. By the time I logged off to clear my head and get dinner, we decided it had to be user permissions. After all, every account on the box used the same PHP instance. Every account had the same rights, etc. It had to be something funny about the profiles, which I’d buy since this server has some accounts that are 15 years old, and it’s the oldest one having the most issues.

    When I picked it back up a day later, I learned something surprising. At first I could get this to run every time on a site that has bbPress, but then I discovered any time I ran a big search (like wp theme status on my multisite, which worked for all other commands), it would also fail. So clearly there’s a memory shenanigan running around here. I tested with and without APC, switched back and forth between PHP handlers (fCGI, suPHP, DSO), and I tried bumping the memory all the way to 128M. Nothing would get me past the weird 37M. In desperation, I changed my php Memory limit to -1. This means no limit. And now it failed on 32M. As I started testing various possibilities, I came across a moment where I set-faulted (this would be from APC cli, don’t use it) and finally grabbed Alex Rabe’s WP Memory Usage, which tells me I was using “Memory : 8.3 of 128 MByte” on the plugins page, so I know WP knows it can have 128M. This lead me down a path of ‘What PHP is CLI using?’ After digging around and verifying it was the same, I started looking at how I’d locked down my server.

    This is where I started banging my head on my keyboard.

    Shell Fork Bomb Protection is a cool thing, in that it stops people from running rough-shod over your server. Of course they way it does this is by restricting the processes you can run via shell. And wp-cli is, say it with me, shell. Once I turned it off, everything worked. I’m not sure if this is something I’d want to do for every server, but since I can count, on one hand, the number of people with access to mine, and I know their passwords are secure, I’m okay with it.

  • Getting involved – Log on, jump in, hang out

    Getting involved – Log on, jump in, hang out

    From WordPress TV

    [wpvideo YhblAsZZ w=640]

    The Passover quip at the end is something anyone who’s been to Seder would understand. There’s a story about four sons: one wise, one wicked, one simple, and one who cannot yet ask a question. It’s for that fourth son that we tell the story of Passover, so he can learn.

    That really is a lot of my mentality with the forums. They don’t know, they may not know how to ask, so lets make the fourth son the first son.

    ETA: The “I don’t have a WordPress related job” part of the talk is no longer true. Starting the 27th of August, I work for DreamHost.

  • Multisite Per Site Registration

    Multisite Per Site Registration

    This post is dedicated to TJ List, who donated to help me get to WCSF. He’s the last post of this ilk, so I’ll stop having these announcements, but I wanted to say thank you all, one more time. My new job starts the 27th, and you all helped!

    Edit: If you want a plugin, see Join My Multisite

    Sometimes people want a way to sign up for the network on specific sites, and not go back to the main site. And I often tell people ‘You need to make a custom page template with the code from the signup page in it.’

    But how? There’s going to be a lot of code in this post, so at the end I’ll give you a link to the whole file you can download and play with. We’re going to go through the steps, however, since we may not be using the same theme, and you’ll need to understand the process.

    Make your Page Template

    First you make a new page template. I always call mine page-template-signup.php because well named files/code don’t need as much inline documentation.

    Since I wanted to build this off of TwentyTwelve, I grabbed the full page template, and pulled that over:

    <?php
    /*
    Template Name: Signup
    */
    
    get_header(); ?>
    
            <div id="primary" class="site-content">
                    <div id="content" role="main">
    
                            My Content Here
    
                    </div><!-- #content -->
            </div><!-- #primary .site-content -->
    
    <?php get_footer(); ?>
    

    Obviously on a first pass, nothing much is going on here. The next step is to open up wp-signup.php and take a look. There’s a lot going on here, but we don’t need all of it.

    First let’s look at what we need to add to the header area. Most of this is just styling and a little tweakage to stop search engines from thinking people need to really find this page, so let’s add the following right above get_header();

    add_action( 'wp_head', 'wp_no_robots' );
    
    // Fix for page title
    $wp_query->is_404 = false;
    
    function wpmu_signup_stylesheet() {
    	?>
    	<style type="text/css">
    		.mu_register { width: 90%; margin:0 auto; }
    		.mu_register form { margin-top: 2em; }
    		.mu_register .error { font-weight:700; padding:10px; color:#333333; background:#FFEBE8; border:1px solid #CC0000; }
    		.mu_register input[type="submit"],
    			.mu_register #blog_title,
    			.mu_register #user_email,
    			.mu_register #blogname,
    			.mu_register #user_name { width:100%; font-size: 24px; margin:5px 0; }
    		.mu_register .prefix_address,
    			.mu_register .suffix_address {font-size: 18px;display:inline; }
    		.mu_register label { font-weight:700; font-size:15px; display:block; margin:10px 0; }
    		.mu_register label.checkbox { display:inline; }
    		.mu_register .mu_alert { font-weight:700; padding:10px; color:#333333; background:#ffffe0; border:1px solid #e6db55; }
    	</style>
    	<?php
    }
    
    add_action( 'wp_head', 'wpmu_signup_stylesheet' );
    &#91;/php&#93;
    
    Just below <code>get_header();</code> we're going to add <code>do_action( 'before_signup_form' );</code>
    
    Then in the 'My Content Here' section, you're going to copy everything from <code><div id="content" class="widecolumn"></code> down to <code><?php do_action( 'after_signup_form' ); ?></code> and put it in there. It's a lot of code, I know. I'm not including it here because of that. Again, check the attached file.
    
    Finally search your file for all instances of <code>wp-signup.php</code> and change them. To what? To whatever you're going to name your page in the next section. I knew I wanted to name my page signup, so I replaced it with that.
    
    <h2>Make Your Page</h2>
    
    <a href="https://halfelf.org/wp-content/uploads/sites/2/2012/08/page-template.jpg"><img src="https://halfelf.org/wp-content/uploads/sites/2/2012/08/page-template-300x222.jpg" alt="Picking Page Template" title="Picking Page Template" width="300" height="222" class="alignleft size-medium wp-image-2509" /></a>Next you make a page. This is easy. You go in to your site, you make a page (I called mine Signup) and you put in <em>no</em> content. Pick the page template called 'signup' and save. I always opt to turn off comments and pingbacks on this page for what I hope are obvious reasons. Don't bother putting in any content to the post. Because we didn't leave in the loop, it wouldn't display.
    
    If that's something you want, then you would leave the loop info in where I had 'My Content Here'
    [php]
    
                            <?php while ( have_posts() ) : the_post(); ?>
                                    <?php get_template_part( 'content', 'page' ); ?>
                                    <?php comments_template( '', true ); ?>
                            <?php endwhile; // end of the loop. ?>
    

    That’s an ‘as you like it’ sort of thing. If you need to leave messages, etc, it’s great.

    And that’s kind of it. Oh, you’ll want to mess with your CSS, but that’s all you need to get started! It even keeps you on the page.

    How it looks…

    Since there are multiple registration options, here’s how they look:

    With Registration Disabled

    User accounts may be registered

    Logged in users may register new sites

    Only Logged In Users Can Make Sites

    Both sites and user accounts can be registered

    Adding Users to Sites

    I know, I said we were done. There’s one more thing. What happens if you want that per site registration to automatically add people to the site they’re on? That is, if someone goes to halfelf.org/signup/ I want them to be added to halfelf.org as a user. The problem with this is when you register for a user account, you may have noticed there’s an ‘extra’ step to confirm. This is where you get that email that says ‘click here…’

    The ‘good’ thing is the URL you get looks like this https://halfelf.org/wp-activate.php?key=0ef92965187a50be and it will take you back to the right site to login! The ‘bad’ thing is it doesn’t actually add you to the site. It will add you any time you create a site, but if you just make a login ID, you get this:

    No Access Is Bad

    As you can see from that URL, it’s sending me back to wp-activate.php, which is something we can’t change in our signup template. If you know you want to add all users to all sites, then you want Multisite User Management, but that isn’t always the case. So what do we do? Option one is to grab a plugin that makes us approve all users, then we can add them as they’re requested. But you don’t want to do manual work, I’d guess.

    The trick is to add an action onto user registration, but only run it per site. So you’d want this in an mu-plugin, and since halfelf happens to be blog , I do this:

    <?php
    global $blog_id;
    if ( $blog_id == 2 ) {
    
      function helf_activate_user( $user_id, $password, $meta )
      {add_user_to_blog( '2', $user_id, get_site_option( 'default_user_role', 'subscriber' ) );}
      add_action( 'wpmu_activate_user', 'helf_activate_user', 10, 3 );
    }
    ?>
    

    That says ‘Hey, if I’m on blog ID 2, when people register, kick them to be a subscriber on this blog. I have mine in a plugin called halfelf-autoregistration.php and it works rather nicely. If someone registers on ipstenu.org, even if they try to login to halfelf, they can’t login because their registration process was on the other site.(I suppose if someone was clever, they could take https://halfelf.org/wp-activate.php?key=0ef92965187a50be and change it to https://ipstenu.org/wp-activate.php?key=0ef92965187a50be to register there, but there’s no change in ‘risk’ between being a network psudeo subscriber and a real subscriber. If I was adding in editors, I’d probably change my mind here and manually validate every new user. I’m trusting in the fact that most people aren’t that clever.)

    Do you have any tricks that help you do this?

    Oh and here’s the file to download. It’s in .txt for security reasons.

    Download Here

  • Capital H Dangit

    Capital H Dangit

    My new gig at DreamHost comes with a minor ‘d’oh!’ and that is it’s a capital H. Which I seem to be incapable of remembering. So I wrote a function. I stole capital_P_dangit() and swapped the WordPress for DreamHost. To save myself from embarrassment, here it is:

    // Capital H in DreamHost
    add_option( 'helf_capital_H_dangit', 'yes', '', 'yes');
    
    if ( get_option( 'helf_capital_H_dangit' ) == 'yes' ) {
        foreach ( array( 'the_content', 'the_title', 'comment_text' ) as $filter )
            add_filter( $filter, 'capital_H_dangit', 11 );
    }
    
    function capital_H_dangit( $text ) {
        // Simple replacement for titles
        if ( 'the_title' === current_filter() )
            return str_replace( 'Dreamhost', 'DreamHost', $text );
        // Still here? Use the more judicious replacement
        static $dblq = false;
          if ( false === $dblq )
            $dblq = _x('&#8220;', 'opening curly quote');
          return str_replace(
            array( ' Dreamhost', '&#8216;Dreamhost', $dblq . 'Dreamhost', '>Dreamhost', '(Dreamhost' ),
            array( ' DreamHost', '&#8216;DreamHost', $dblq . 'DreamHost', '>DreamHost', '(DreamHost' ),
          $text );
    }
    

    Now. Here’s where it gets fun. No ‘hacks’ posts will be affected by this code! Otherwise how would I show it to you here? Normally this is where you would just run remove_filter( 'the_content', 'capital_H_dangit', 11 ); in the functions file for your theme. Due to the way I’ve wrapped my various functions into mu-plugins, the down and dirty way was to wrap the above block of code with a check for if ( $blog_id != 2 ) { { ... }.

    Most of the time you won’t care about things like this. I just needed it so I could demonstrate code. I’ve done the normal filter remove here so I can also say ‘Wordpress’ in my code related posts. For proof this works, I assure you, 100%, that I typed in ‘Dreamhost’ over in my post about quitting my job and going to work for them.

    Sorry about that, Simon!