Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • 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!

  • Managed Themes Have A Place

    Managed Themes Have A Place

    This post is dedicated to Helen Hou-Sandi, who donated to help me get to WCSF. Helen and I like to Pass the Hat, to the amusement of my former firewall team. She also encouraged me to apply for the WP job I got last week. Thanks, Helen!

    I’ve been using a managed theme on my main site (ipstenu.org) for the last few months, and I’ve decided I really like it. I’ve also started to sort out the kind of people who should be using it, and it’s not everyone.

    Let’s start by breaking down themes into their logical types:

    • A Theme – These are things like TwentyEleven, that you simply use as-is.
    • A Child Theme – These are for tweaks you can’t make via plugins or css.
    • A Parent Theme – This is a theme you know you’re going to extend.
    • A Theme Framework – Similar to a parent theme, this is a theme you build off of. It may, or may not, be a parent, however. See ThemeHybrid’s themes, or the Bootstrap theme.
    • A Managed Theme – A theme that acts like a framework and a child at the same time.

    PuzzlesThe differences between these types is slim and sounds like I’m arguing semantics. The weird magic of it all is that themes are themes, and there’s not a whole lot of difference between everything. So maybe I’m looking at themes wrong. The point of themes is that you should be able to make your site look how you want to, no matter your skill level. The problem is that with a low skill level, you don’t know how to do the things you want to. This is where managed themes come in.

    A managed theme holds your hands, and takes the burden of knowing ‘code’ off of the user. While I’m not a fan of lowering the bar too much, there’s a point when we need to make the software easy enough in all aspects and not just some. WordPress isn’t perfect, and while it’s amazing a lot of things, there’s really too much going on in others. This is why there’s room for something like Tumblr, where it’s very easy to post (if hard to make your site look ‘right’). I see WordPress needing some improvement on posting, making it much easier for people to just write, and somehow separating that from the ‘managing a website’ part.

    But at the same time, managing the website, making it look right, is crazy hard. There are a lot of options and a lot of possibilities. Anyone who’s tried to make a site for someone else knows how much like banging your head on a wall it can be. So when you’re new, and you can’t afford to hire the big guys to make a site, but you want flexibility without having to learn code, where do you go?

    Managed Themes.

    Look, I love a sexy Theme Framework. I’m a huge fan of ThemeHybrid. But part of why I love it is that I can get into the nitty gritty code, tweak functions, and go to the races. I spend a lot of time tweaking backends and testing layouts and messing with functions. But not everyone likes to do that, nor should they. I’m not a super snazzy theme designer, they’re not super awesome writers, it’s differences that make the world go around.

    For the last few months, I’ve been using Genesis Theme and I have to say, if I was going to make a site to turn over to someone who I knew was somewhat savvy but not super technical, I’d pick that. It’s not ‘easy’, but this is something that a middle-of-the-road person could pick up, make their way through, and grow and advance as needed. It’s a perfect way to make your site not look ‘standard’ while still not meaning you have to be all action/hook/function skilled. After all, it takes a while to grow into that.

    Managed themes aren’t for ‘me’ most of the time. I know that’s weird to say when you note that I’m using one. I’m really a framework sort of girl. I love the nuts and bolts. But when I don’t want to spend a whole day (like I just did) tweaking a child theme into submission, and just pick up and go and not look like an out of the box site, a Managed Theme is the way to go. I don’t have to worry about telling someone ‘Just edit the functions.php…’ when they want to change something. There’s a nice GUI for them.

    I’ve played with a couple, but I have to say the only one that impressed me enough to give them a second chance was StudioPress’ Genesis Theme. Part of why I gave them a shot was because one of my best friends works there. But after half an hour of using it, I thought “This is easy.”

    Who are Managed Themes for? They’re not for the newbies, and they’re not for the masters of all they survey. But if you, like me, don’t really like designing themes, and you’re not always wanting to pick apart code, grab a managed theme. I may still lean towards the Parent Theme Templates for myself, but right now, looking at a site my father wants, I’m looking at those managed themes.

    They’re pretty darn cool.

  • My Custom PostTypes Live in MU

    My Custom PostTypes Live in MU

    This post is dedicated to Boone Gorges (aka ‘WP Boone’ to me), who donated to help me get to WCSF. My brother is also named Boone, so even if WP Boone wasn’t so awesome, I’d like him.

    Brain - You must useCustom Post Types. I really dig them, as a great way to make ‘kind of’ pages, without making a million pages. They don’t ‘order’ as well as pages, and default to publish date, but really that could be adjusted. The point, and I have one, is that they’re often a great alternative to Multisite, and I use them a lot.

    There are lots of plugins that can make these for you, but I prefer to do it myself in a function file, becuase it gives me more flexibility for what is, let’s face it, a complicated sort of thing.

    In this example, I’m going to make a ‘drawing’ custom post-type, like the one I just added to my photoblog. First I made a file called photo-cpt.php and in it put a header:

    <?php
    /*
    Drawing Name: Photos CPTs
    Drawing URI: http://photos.ipstenu.org/
    Description: All Photos custom code.
    Version: 1.0
    */
    ?>
    

    Notice I am not telling you to put this in a functions file. I never put my CPT in my theme’s function, becuase I always make my CPTs able to work with any theme. By making it a stand-alone ‘plugin’ file, I can put it in mu-plugins and run it automatically. More on this in a minute.

    The code itself is split into two sections. I learned this method from Justin Tadlock, who has a nice, if very techy, primer on Custom Post Types in WordPress. I freely admit, once I figured this code out, I saved it off line and copy/paste it where I need, replacing the terms (Drawing/s) for what the new CPT is.

    <?php
    	add_action( 'init', 'create_photos_post_types' );
    
    	function create_photos_post_types() {
    
             /* Labels for the Drawing post type. */
            $drawings_labels = array(
                    'name' => __( 'Drawings', $domain ),
                    'singular_name' => __( 'Drawing', $domain ),
                    'add_new' => __( 'Add New', $domain ),
                    'add_new_item' => __( 'Add New Drawing', $domain ),
                    'edit' => __( 'Edit', $domain ),
                    'edit_item' => __( 'Edit Drawing', $domain ),
                    'new_item' => __( 'New Drawing', $domain ),
                    'view' => __( 'View Drawing', $domain ),
                    'view_item' => __( 'View Drawing', $domain ),
                    'search_items' => __( 'Search drawings', $domain ),
                    'not_found' => __( 'No drawings found', $domain ),
                    'not_found_in_trash' => __( 'No drawings found in Trash', $domain ),
            );
    
            /* Arguments for the Drawing post type. */
            $drawings_args = array(
                    'labels' => $drawings_labels,
                    'capability_type' => 'post',
                    'public' => true,
                    'has_archive' => true,
                    'can_export' => true,
                    'query_var' => true,
                    'rewrite' => array( 'slug' => 'drawings', 'with_front' => true ),
                    'taxonomies' => array( 'post_tag', 'category'),
                    'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'custom-fields', "photos-post-settings" ),
            );
    
            /* Register the Drawing post type. */
            register_post_type( apply_filters( 'photos_drawings_post_type', 'drawings' ), apply_filters( 'photos_drawings_post_type_args', $drawings_args ) );
    	}
    ?>
    

    Looking at this, it’s actually surprisingly straightforward what I’m adding and where. The weird code of $domain is a variable I’ve defined elsewhere, and lets me translate if I need to. I probably won’t but it’s a good practice to get into. By splitting out my labels into their own variable, I’m able to break them up and make it more readable. As Otto says, good code doesn’t need inline documentation becuase it’s readable. You can see the names, and the fields, I’m adding, and they magically become self-explanatory. Then in my drawing arguments, I again make a variable with the settings. Pull in the complex labels, then I can break out the next arguments into something readable.

    Trucks and Buses Must Use Low Gear You can read all the various options in the codex article for register_post_type(), which is the function I finally call at the end.

    If you wonder why I have the whole thing wrapped in an action, it’s becuase in other places I actually add multiple post types to a site. This lets me put them all in one action, call it once, and walk away. As long as each CPT has a label, arguments, and registration, they’ll all run.

    Below that action, I have one to add my CPT to my ‘right now’ section on the dashboard. I got this from James Laws over at WP Ninjas, and really it’s one of my favorite things.

    <?php
    // Adding to Right Now
    	add_action( 'right_now_content_table_end', 'photos_right_now' );
     
    	function photos_right_now() {
      
              // drawings
              $num_drawings = wp_count_posts( 'drawings' );
              $num_p = number_format_i18n( $num_drawings->publish );
              $text_p = _n( 'drawings', 'drawings', intval($num_drawings->publish) );
              if ( current_user_can( 'administrator' ) ) {
                $num_p = "<a href='edit.php?post_type=drawings'>$num_p</a>";
                $text_p = "<a href='edit.php?post_type=drawings'>$text_p</a>";
              }
              echo "\n\t".'<tr class="first">';
              echo "\n\t".'<td class="first b b-drawings">' . $num_p . '</td>';
              echo "\n\t".'<td class="t drawings">' . $text_p . '</td>';
              echo "\n\t".'</tr>';
    
    	}
    ?>
    

    Taking a step back, there’s this interesting line in my arguments:

    'taxonomies' => array( 'post_tag', 'category'),
    

    All this does is say ‘I want to use post tags and categories in my CPT.’ And in this case, it’s the same ones as I use for my normal posts. You can do a lot more with it if you wanted, but I believe in KISS.

    To loop back around, however, why do I put this in an mu-plugin? First and formost, it’s portable. No matter what theme I use, it comes with me. As I talk about this method in No Children Necessary, it really comes into play here more than anywhere else. On a single, traditional, WP install, I just toss it in and walk away. It’s code, I don’t want my end-users playing with it, so a non-editable file is perfect. For Multisite, I really just add if ( $blog_id == 2 ) { ... } around the whole thing. I could do it just on the actions, but this is easier for me. I can see right away ‘Oh! Site 2.’

    This is obviously not going to work for everyone, but sometimes just looking at the next option will give you a new idea.

  • Getting Involved – Notes

    Getting Involved – Notes

    In case you missed it, I spoke Saturday, August 4th, at WordCamp San Francisco. I had 15 minutes to talk and was asked to talk about the community, getting involved, and that sort of thing. Knowing there was a short time, I decided not to do slides, and instead wrote ten 3×5 cards with my notes. I’m kind of a badass that way.

    The video should be up online in a little while, and I’ll embed it here, but for now, here are my cards.

    WCSF Logo

    1. Getting Involved: Log On, Jump In, Help Out
    2. I volunteer for WP. Forum mod, Ideas org/despamming, plugins, Make support (lead thingy)
    3. Instead of talking about me, I want to explain why you, the community, are important. Encourage you to jump in and help out.
    4. What is the community? Writers/Bloggers, plugin/theme devs, people who dream in code, all of us.
    5. Giving back helps. What’s the point of WP? Part of good software is how it works, and the community is the embodiment there of. Without us, it’s nothing.
    6. Why should I help? Becuase you know and they don’t. Because you will learn more. Becuase you will be inspires.
    7. How can I help?
      1. Write Questions: use WP, come back with questions & suggestions
      2. Answer Questions: help out with those Qs! Learn what happened and why
      3. Fix things: Educate, code, educate!
    8. But … I don’t know the answers. They’re mean. They’re stupid/arrogant/ignorant. They’re impatient.
    9. No one is more important. No users == less inovation. No devs == less change.
    10. Just do it! You were new (we aren’t born knowing). There are no stupid qustions. Be patient (everyone). Make WP Better.

    There you go! When the video’s up, I’ll elaborate more, and comment on what I was thinking (other than ‘don’t rush’ and ‘don’t puke’). I did suggest people answer five questions for every one they ask, since you guys are smart cookies and I know you can bang out five easy questions in 30 minutes. Half an hour. I promise it’ll make you feel better.

    Also the video has an extra secret Passover joke.