Half-Elf on Tech

Thoughts From a Professional Lesbian

Category: How To

  • WordPress Media Library: Show ID

    WordPress Media Library: Show ID

    random-rotation-galleryWhile this is considerably less of an issue with the new Media Uploader, and how it inserts your gallery code, this used to be a hassle. The old [gallery] code would just be that, a short tag, and if included all images attached to a post. So if you wanted it to exclude some images, you had to figure out their IDs, or remove them from the post.

    I used to have to show people how to do this all the time. Hover over the image, note the URL, bleh bleah bleaaaaaaaaah.

    So what if the images showed the IDs? Hey! You can do that with this function!

    function column_id($columns) {
        $columns['colID'] = __('ID');
        return $columns;
    }
    add_filter( 'manage_media_columns', 'column_id' );
    function column_id_row($columnName, $columnID){
        if($columnName == 'colID'){
           echo $columnID;
        }
    }
    add_filter( 'manage_media_custom_column', 'column_id_row', 10, 2 );
    

    And there you go. I don’t actually use this anymore, but it was sitting in my scrapbook of functions.

    If you’re wondering about the right way to handle galleries today, the gallery editor lets you configure what images are and aren’t in it through a GUI, so you don’t need to mess with this. Just click on the gallery to edit it, remove the images you don’t want, add the new ones, and off you go. About the only thing it doesn’t do is let me select how I want the images to like (URL, file, or none), and I still don’t have the option to link to an external URL. Ah well.

  • How To Duplicate Content

    How To Duplicate Content

    I’ve talked about this before. 100% duplication of content on multiple sites is bad. So why am I going to tell you how to do it? And better, why am I going to tell you how to do it without Multisite? Because as a proof-of-concept, it was interesting.

    The rest of this post tells you how to do something I don’t advocate, nor will I support. If you have a better way, or improvements, please leave comments. Otherwise, you’re on your own when you do this. I will not help you do it in any way, shape, or form.

    Honestly, I still think this is a pretty silly idea. Duplicating content is a terrible user experience, and I still flat-out decline to accept any work for doing this. Sharing content is one thing, but 100% duplication of sites makes no sense at all to me. Yoast also says it’s a bad idea. But, if you really are totally 100% dedicated to do this, and you absolutely are going to, damn the torpedos, then you should do this in the least computationally expensive way possible. And that would be a single install.

    Now all that said, this means you’ll need to do a lot of monkey-work, so why do I call this ‘easier’? In many ways, easy is relative and this will be hard, complicated, and may I stress, entirely unnecessary. You’re going the hard way around for something that good planning and a solid understanding of the Internet totally negates. Remember the absolute rule of the Internet: Use one URL per page and never change that URL. (With all rules, there are exceptions, of course.)

    The way to make all this work, without Multisite, is by tricking your domain a little. There’s a neat trick with parking (or mirroring, depends on your host) domains, that lets you keep the other domain URL in your browser’s address bar. That’s what I do with this site, actually, halfelf.org is parked on top ipstenu.org. And with a park, the URL always stays as halfelf.org. Hey look! Two URLs, one site! Multisite has secret sauce to know “Someone’s coming to HalfElf, send ’em to site .” But on a single site, all my links would still be ipstenu.org and not halfelf.org.

    Now how do you use this to duplicate content? You use relative URLs.

    So here’s a real example. I have twofer.elftest.net set up to mirror plugins.elftest.net (which will give you a coming soon page, it’s just where I like to blow things up for tests).

    In the beginning of this post, when I linked to my old post about Duplication Dilution, the URL was https://halfelf.org/2012/duplication-dillution/ and that is what we call an absolute URL. Because I’m mapping domains, I can leave those in without worry, but if I wasn’t, I’d change that URL to /2012/duplication-dillution/ instead. Right away this makes my URLs entirely relative, no domain name included, and I’m off to the races.

    This doesn’t solve everything, though. See, WordPress really wants to use absolute URLs. There are plugins like root relative URLs, and those will help a lot. None of them back-ports your existing posts, though, so for that it’s nothing for it but to search/replace the DB and change your post content.(ONLY change your post content. Do not change GUIDs!) I really like those plugins because now for a new post, when I add a link and chose to link to existing content, it happily works:

    addinglink

    And when I add an image, it too smartly handles as I want it to:

    addingimages

    That’s the easy part of all this, though. Now you have to disable canonical URLs, so that you don’t end up with even more of the dread duplicate content penalty in WordPress.

    remove_action('wp_head', 'rel_canonical');
    

    This also stops WP from redirecting things like http://plugins.elftest.net/?p=1 as well, however, so keep that in mind. Of course, that’s what you wanted. But they don’t address the problem of your source code. If I view source on twofer.elftest.net, it still showed plugins.elftest.net, and that would be a problem for images and themes. You’ll need to toss in this to your wp-config.php, which will dynamically change your URL to be whatever URL I’m visiting from, so that changes automatically. Awesome.

    define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST']);
    define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
    define('DOMAIN_CURRENT_SITE', $_SERVER['HTTP_HOST']);
    

    Now I want to tell WordPress that wp-content is not in URL/wp-content/ so let’s just put this in and make it relative too!

    define('WP_CONTENT_URL', '/wp-content');
    

    I’m still going to have to search and replace my old post content (I used Velvet Blues for this):

    Velvet Blue Update

    But that didn’t address the problem of the source code. 90% of WP now thinks it’s all on twofer, which is what I wanted, but look at XMLRPC:

    sourcecode

    the_more_you_know2And even better, when I try to log in via twofer, it still says I’m going to plugins. Oh and it doesn’t pass through cookies, so really, I never log in to Twofer. Realistically? This isn’t a problem. I’m always going to use plugins.elftest for all this when I log in on the backend, and since the convenience of all this was meant for the front end, and it’s just pingbacks. And why is that? Honestly, I don’t know. I have a guess that since, at WordPress’ heart, the site is always plugins, the absolute URL there has to be what it is, but in so far as all that goes, I think it meets the needs of why most people want to do this.

    Conclusions? You can do this. If you wanted to, you can hardcode the theme so the domain you visit the site with will dynamically change the header image, or widgets, or anything else you want. PHP is pretty cool that way and WordPress is too. But I would never do it, except as an experiment to see what I could do it at all.

  • Recovering Your Cape

    Recovering Your Cape

    One of the odder “hacks” out there is one where the person, once they get in, de-frocks your Super Admin on a Multisite. This isn’t always a hack, sometimes it’s just a simple mistake.

    To quote my friend Jen Mylo:

    1. People give away admin rights like logo-encrusted keychains at a car show and then the new admins abuse the power.
    2. Someone who has admin rights deservedly but doesn’t know code makes a mistake.

    […]

    Some people make bad decisions about who to give admin roles.

    There’s an extra level of problems with making everyone and their pet monkey a super-admin on Multisite. You may think it’s a great thing, because now someone else can add new users, install plugins, edit themes and plugins, and of course, use iframes and PHP and such in widgets.

    tumblr_md8hekGkk31qc184to1_500We run a Multisite at work, and they let me ‘secure it up’ recently. The first thing I did was demote pretty much everyone except five of us to ‘Editor.’ I told them all that I’d done this, and if they found something they couldn’t do, tell me, and I’d fix it. At this point, I’ve changed only three people to Admin, and dropped even more to ‘Author.’ Why? Because they don’t need to have high levels of access to do what they need to do! The admins on the site can tweak theme settings, play with widgets, and add ‘existing users.’ Everyone else? They just write content. Heck, most of them don’t even need to be Editors, but we gave them that level so they could help us copy-edit other posts. Two people complained “I need Super Admin access!” and I gave them my best Enda: NO CAPES.

    Limit your admins, and there is less of a chance someone will accidentally remove access from the wrong person.

    So now that that’s out of the way, how do you get it back?

    Normally, reinstating an admin account is pretty easy. You go in via mySQL, pop open the wp_usermeta table, find your ID, and toss this in for meta_value for wp_capabilities: a:1:{s:13:"administrator";b:1;} That won’t restore all the roles, if you happen to be using Role Scoper, or some other management tool, but if you’ve got that, you can do anything. If you’re using WP-CLI, wp user update 1 --role=administrator (assuming you’re user ID 1).

    Screen Shot 2013-06-21 at 11.34.20 AM

    There’s a sidebar/caveat to this. Sometimes this doesn’t work, and it happens if you change your DB prefix. So normally you have the prefix wp_ and the table wp_options. In that table you have a option named wp_user_roles and everything works. But then you make a new site, and you pick a different DB prefix, maybe you heard it was more secure, or maybe you wanted both tables in the same DB. Either way, now you have wp_wdssrr_options instead, and when you copy over your old options content, no one can log in. It’s because you have to rename that option to wp_wdssrr_user_roles

    Screen Shot 2013-06-25 at 10.00.51 AM

    I just had a site with this problem last week.

    NomadTrip_7091 On the other hand, getting back Super Admin access is less straightforward, but by no means is it impossible.

    1. Go into wp_sitemeta and look for site_admins.
    2. In there you will see something like this: a:1:{i:0;s:7:"Ipstenu";}
    3. If your userID is ‘superman’ then it would be a:1:{i:0;s:8:"superman";}

    Capitalization and stringlength matter. Add one user, and use that to correctly restore power to the others.

    Can you do this via WP-CLI? Yes, if you’re on the latest versions. Kind of. You can get a list of super admins via wp network-meta get 1 site_admins and in theory wp network-meta update 1 site_admins USERNAME would work except that the data is serialized. I opened a ticket with WP-CLI, and it’s a ‘plugin territory’ issue right now, so I’ll have to see if I can code it myself.

  • Shortcode: MLB.TV

    Shortcode: MLB.TV

    I like baseball, I like the Indians. I like embedding content. Why MLB.tv likes to make their stuff not easily embeddable is beyond me. I think [mlbtv id=28142247] is way easier to deal with if I’m using the visual editor. I grabbed the default sizes from their settings.

    <?php 
    // MLB.TV Shortcode - Better code by Konstantin Kovshenin
    // &#91;mlbtv id="###" width="480" height="270"&#93;
    function mlbtv_shortcode( $attr, $content = '' ) {
        $attr = shortcode_atts( array(
            'id' => null,
            'width' => 400,
            'height' => 224,
        ), $attr );
     
        $attr = array_map( 'absint', $attr );
        $url = add_query_arg( array(
            'content_id' => $attr['id'],
            'width' => $attr['width'],
            'height' => $attr['height'],
            'property' => 'mlb',
        ), 'http://wapc.mlb.com/shared/video/embed/embed.html' );
     
        return sprintf( '<iframe src="%s" width="%d" height="%d" frameborder="0">Your browser does not support iframes.</iframe>', esc_url( $url ), $attr['width'], $attr['height'] );
    }
    add_shortcode( 'mlbtv', 'mlbtv_shortcode' );
    

    [mlbtv id=28142247]

    Looks just fine.

  • Migrating to DreamPress

    I should start with the note: You do not need to do this. We’re finishing up the last bells and whistles on a script that will handle all this for you if you have a One-Click-Install, but if you really just can’t wait or had a manual install, here’s what you’ll need to do. Keep in mind, there will be about an hour where your hosting will ‘vanish.’ In the words of Ford Prefect, don’t panic.

     

    Again, you don’t have to do this. We will have a magic button soon enough. That’s why this isn’t going up on the Wiki, it’s really not going to be (long term) useful except to people who love experimentation.

    We have a magic button!

    magicbutton

    But if you still want to do it manually, read on.

    So you saw the news about DreamPress and read our bragging post about it? You got super super excited and then bummed, because the magic button isn’t done yet? Well… Okay, you can migrate manually (I did it for this site yesterday), but you need to know shell. You can do all this with FTP, but it’ll take way longer.

    If you just want to make a new domain, read DreamHost Wiki: DreamPress, and you’re good to go! Otherwise, pull the hat down snugly, because here we go!

    1. Remove Hosting

    1-removehosting

    Yes, I know. It’s scary. By removing hosting you will turn your site to DNS only. This is OKAY. Your files and your DB will remain exactly where they are. The Remove button is right under ‘Fully Hosted / User : elftest‘ so just click that.

    2-see-DNSonly

    See? Now it’s DNS only.

    2. Add DreamPress hosting

    Go to https://panel.dreamhost.com/index.cgi?tree=domain.wordpress& and add a new site.

    3-addDP

    You should see a happy green box telling you that it will take 15-30 minutes to provision you the site. Sorry about the wait time, but we’re actually building you the server stuff on the fly. It’s special.

    4-success

    While you’re waiting, let’s get some things done.

    3. Export the old DB

    Everything is perfectly safe and sound, so just go ahead and do that. Save it locally to your computer.

    Go to https://panel.dreamhost.com/index.cgi?tree=goodies.mysql& and log in to your SQL database. The directions are the same as our normal Backup MySQL ones, so just go and do that.

    If you’re Command Line savvy, you can do this via WP-CLI.

    ssh oldaccount@oldserver.dreamhost.com
    cd example.com
    wp db export
    

    That will reply with “Success: Exported to example_com.sql”

    By the way, you’ll need to have the server name (not your domain name) in order to SSH in, as we’ve already pointed your domain to DreamPress. It’ll be something like ps10000 which makes your SSH ps10000.dreamhost.com. You can leave the SQL file there, we’ll pick it up later on in the show.

    As soon as you get that email saying “Yay! DreamPress for you!” we’ll ignore the email’s directions and skip on to…

    4. Get the new credentials for both SQL and SFTP.

    On the DreamPress page, you’ll see your new site info.

    5-newinfo

    You’ll be able to find the new passwords at the usual locations. In the case of the user account (which will be something like wp_kxezav), you’ll want to set it to something you know. While you’re in there, change the account type to “Shell account – allows SFTP/FTP plus ssh access.” I personally also check to disallow FTP, for security. I also like to rename the account something like ‘ElfTest – DP’ so I know this account is for ElfTest on DreamPress.

    By the way, you may wonder “Why can’t I have one ID for all my domains on DreamPress?” and the answer is twofold. First, we’re charging you per site. Yes, site. Secondly, security. If one account gets hacked, the others are safe. This is a good thing!

    5. SSH into your new account

    It’ll be ssh wp_kxezav@ps1121212.dreamhostps.com or such and this will dump you into not the domain, but the folder above it. This is important! You need to be in the example.com folder in order to do anything. Notice also how the domain is suddenly dreamhostps.com and not just dreamhost.com? Also important.

    By the way, if you’re going to be using a lot of SSH, you should set up passwordless SSH access. It’s perfectly safe (in fact, safer than entering a password), and has to be set up per computer but .. how many of us use more than one computer? Hush, geeks.

    6. Super power time! Let’s copy everything over!

    Actually, let’s delete everything first. Yes, I know what I just said. There are reasons. This is just faster. I’m super lazy, so I first opened up wp-config.php and copied the SQL data for the NEW database.

    // ** MySQL settings - You can get this info from your web host ** //
    /** The name of the database for WordPress */
    define('DB_NAME', 'example_com');
    
    /** MySQL database username */
    define('DB_USER', 'examplecom1');
    
    /** MySQL database password */
    define('DB_PASSWORD', 'likeaflaninthecupboard');
    
    /** MySQL hostname */
    define('DB_HOST', 'mysql-1.example.com');
    

    Obviously changed for my protection. You’d never publicize your passwords. Right? RIGHT? Good. I saved this to a text file on my laptop for the time being. Now let’s delete:

    ssh newuser@ps1121212.dreamhostps.com
    cd example.com
    rm -rf *
    

    This wipes out everything in my domain’s folder. Make 100% absolute sure you got the right folder! Once you’ve done it, let’s copy things over!

    scp -r olduser@oldserver.dreamhost.com:example.com/ .
    

    SCP is ‘Secure Copy’, and is a fancy pants Unix Command. I’m fond of it. You’ll notice that I said to use ‘oldserver.dreamhost.com’ and not ‘example.com’ and this is because we’ve already pointed your domain to DreamPress. Zoing! When you do this, you’ll be prompted for a password.

    Then you’ll get a mile of stuff like this:

    wp-config.php                                                  100% 3583     3.5KB/s   00:01
    xmlrpc.php                                                     100% 2719     2.7KB/s   00:00
    readme.html                                                    100% 9177     9.0KB/s   00:00
    admin-bar-sprite.png                                           100% 2470     2.4KB/s   00:00
    

    This is SCP copying everything over, safe and sound.

    7. Change your Database Stuff

    There are two parts here. First you want to copy that DB stuff you saved before into the wp-config.php file, replacing the configuration you had there before. Second you want to import that backed up database into the new DB.

    You can do this via phpMyAdmin if you want, but if you’re using wp-cli (and you should, it’s awesome), you can do this:

    wp db import example_com.sql
    

    Whaaaaat? How did that work? Remember when you exported on the old setup and then SCP’d the files over? Guess who came with! That’s right, you slipped your DB over nice and fast, and boom goes the dynamite, you’re in.

    8. Have a beer!

    I always end things with a celebratory something. Your URLs didn’t change, so you’ve got nothing to worry about. Once you’re sure everything’s good, go ahead and delete the old user ID as long as you are 100% certain you’re not still using it!!! Remember, a lot of us use the same IDs for multiple domains.

  • When Your Code Doesn’t Self-Alert…

    When Your Code Doesn’t Self-Alert…

    If you don’t want to read this whole post, there’s a big takeaway for anyone who releases code: Please make sure you have an easy way for people to be notified to a new release.

    The Story…

    Alert me nowI use WordPress a lot. It’s made me lazy on a lot of things, like version control. It’s also made me incredibly complacent when it comes to updates. You see, WordPress has a massive API system and servers which allow you to get in-app alerts to any needed updates. Click to upgrade and done. It’s second only to Chrome, which just updates.

    Now there are pros and cons about automated updates, and some things, like my server software? Hellz no, son, I don’t auto-upgrade that! Yes, I auto-upgrade cPanel and other server tools that I added on, but PHP and Apache and MySQL? No, those are things I have to stop and make damned sure I know what I’m doing. Why? Because they’re not ‘add on’ software, they’re the core functionality of my entire webserver, and if I mess them up, I am up shit-creek.

    If you’d asked me last year ‘Should WordPress auto update itself like Chrome?’ I would have shouted no, very loudly. And now here I am, doing it. Personally I’ve been using Gary’s Automatic Updater on all my sites for months now, because I know my WordPress setup is tight. I love the Chrome and Firefox auto updates, because I don’t customize those things ever. While I do customize the hell out of WordPress, I do it smart and I do it right. My code is doing_it_right() and the plugins or themes I add on to my sites are all well vetted and Elf Approved. The same can’t be said for everyone, but after a lot of thinking, I think if WordPress auto-updated, people would have an initial clamor of pain with all the shitty code out there that broke, and then the bad code would Darwin itself right on out of use.

    But that’s not the point of this. In my head there’s a difference between ‘core software’ like PHP, and ‘app software’ like WordPress. The lines are clear, they should never be crossed. Auto-Updating works for apps, not for core. And what happens when your app doesn’t even auto-alert for updates? How do you handle updates?

    I’ve already mastered using git as a ‘deployment’ tool, and svn has been old hat for me. That means I know how to quickly update my code, but I need to know when to do this.

    The Solutions…

    There is a light at the end of the tunnel. There are some easy ways you can keep track and, conversely to the devs, make it easy to keep people up to date, and it all starts with the code’s website. You do have a website for your code, right?

    Check the website

    If there’s a blog, there’s probably an RSS feed. This is really easy, since most (if not all) blog and CMS tools use RSS.

    about-groupsNo RSS? No blog? Maybe there’s a mailing list. This is actually my favorite option. I hate email, but I love getting emails for software updates like that. If that’s not your thing, see if the mailing list has an RSS feed. I know people use Google Groups for a cheap mailing list, and if you visit the Groups page and click on the about link (see the image, not the dropdown, the link), you get a whole mess of RSS options!

    rss-options-groups

    This only works for public groups, but why would a private group be an announcement list for your app releases anyway? If it’s private, get used to email.

    Speaking of mailing lists, MailMan, my list of choice, does not have RSS feeds. It’s the old spavined mule of lists, I know, but for people who love it, check out MailMan-to-RSS.(The irony I feel in writing that, which is the opposite of how I handle things with my post2email plugin, is deep and unfathomable.)

    But what about those other guys? You know who I mean, the guys who use GitHub as not just a version control tool but their code host? After all, Github Pages are pretty cool, and free, so why not? Time for a practical example.

    My amazing friend Mel made a site for Dashicons. They’re like Genericons for your WP Dashboard, and if you’re using MP6, you’re looking at them now. (Mel pointed out to me she did not make all the icons, only some, but the site is hers, so her I pick on.) The site is awesome. It’s fantastic that people can make sites like that, and you can even put a custom domain on it.

    But look at it! No feeds!

    Thankfully, Github pages are built on Jekyll, and you can set up feeds. But let’s be frank, if it’s not automatically set up for people, they’re not going to do it. And most people don’t do the ‘blog’ part of their Github page sites either. Now what?

    Well thankfully, for anything on GitHub, since most people push releases with tags (note to self…), you can use this for rss: https://github.com/user/project/tags.atom — Sadly, I couldn’t find one for branches.

    The Real Answer…

    Look, at the end of the day, if you’re releasing public code, it’s incumbent upon you to make a way for your users to be able to find out, easily, when you’ve updated. Expecting them to come to your site and check is not going to work. Making an automated way to push your code, your changelog, and your update notices to people, will put it all in one go for you and make it easy. If, like me, you’re afraid people will end up getting too many alerts, make it a blog post and only do it when you know you’re ready.

    Making it easier to get alerts for needed upgrades is going to make everything safer, in the long run. Think of all the security patches people are missing, just because we don’t get notified of them!

    Now if you’ll excuse me, I need to sort out how to better use branches and tags.