Half-Elf on Tech

Thoughts From a Professional Lesbian

Category: How To

  • No Notice For Upgrades?

    No Notice For Upgrades?

    About a week ago I realized I’d not see an email with the subject “[Ipstenu.Org] Background updates have finished” in a long time. A really long time. Like so long that when I looked in my email trash, there wasn’t one.

    This was bad, because on Ipstenu.org I’m running trunk WordPress, which means I should get two emails a day about this. I ran to my server and scanned logs for 30 days. Nothing. And that was really bad.

    I’ve been using Advanced Automatic Updates for a long time, and I love it, it works well, but it wasn’t working ‘right’ for some reason, because it wasn’t emailing me on that one site, so I uninstalled it. The problem there is that without it, how would I upgrade plugins and themes? Since I know I can control the upgrades with filters, I decided to make an mu-plugin to handle just that.

    And that was when I saw I already had an mu-plugin called upgrades.php with this:

    WordPress site: https://ipstenu.org/
    The following plugins were successfully updated:
    * SUCCESS: Akismet

    Perfect!

    I don’t know how fun that story was, Benny, but that’s what happened.

  • Multisite Favicons

    Multisite Favicons

    One of the challenges with WordPress Multisite is that everything is on the same install. This means something that is rather trivial, like a favicon, becomes exceptionally complex and tiresome.

    On a normal site, when I want to make a favicon, I just toss the file into my main HTML folder, next to that .htaccess file, and I’m done. Now, for me it’s a bit of an extra step because I use StudioPress’ Genesis theme, and it applies its own favicon. It’s probably the only thing about Genesis that makes me annoyed, though it’s right next to when my host does that for me. Still, there’s a trick with Genesis.

    Because of Genesis

    Genesis is my parent theme, and it defines my favicon. So I have to delete its and put in mine:

    // No, you may not have your favicon
    remove_action('genesis_meta', 'genesis_load_favicon');
    
    add_filter( 'genesis_pre_load_favicon', 'halfelf_favicon_filter' );
    function halfelf_favicon_filter( $favicon_url ) {
    	return 'https://halfelf.org/code/images/favicons/halfelf.ico';
    }
    

    And it’s that simple.

    But I’m talking about Multisite, and I want to have a different favicon per site, I end up facing a new challenge.

    Because of Genesis and Multisite

    I still need to tell Genesis to shove it, but then I need to check what site I’m on and call the right favicon per site and this works very well. I’m using it today (you can see the code on that other link). But what if there was another option? What if I didn’t have to code it? Because the real problem with that code is I have to do it! If someone wants a new site to have their own favicon, I have to go in and add it to my mu-plugin, save it, commit it, and push it. Ew.

    Jetpack Site Icons

    Jetpack has a newish feature called Site Icon. With that module activated, I can allow each site to upload their own site icon and it will make a mobile icon too where I won’t have to.

    Uploading my Space Invader

    For a Multisite running Jetpack auto-activated on all sites, this is perfect. And yes, I do that because it saves me a headache of having to set it up later. I allow all sites to connect on their own, but I can also control all that from the network admin.

    So what does that old code look like now?

    With Genesis and Jetpack

    Now my code is simple. For everyone, I kill the default favicon, and then I set my own:

    // No, you may not have your favicon
    remove_action('genesis_meta', 'genesis_load_favicon');
    
    global $blog_id;
    
    add_filter( 'genesis_pre_load_favicon', 'example_favicon_filter' );
    function ipstenu_favicon_filter( $favicon_url ) {
    	return 'http://example.com/images/favicons/example.ico';
    }
    

    And the best part is if I set a site icon in Jetpack, it uses that instead.

    Best of both worlds.

  • Git The Master Race

    Git The Master Race

    I was working on a project, a side project for fun with a friend, and she expressed a slight worry. We weren’t using any versioning on our theme or mu-plugins code. Or anything else for that matter. There were three of us. We thought about using GitHub until I pointed out I had git on my server, where I was hosting it all.

    In many ways I don’t use git like a ‘normal’ person, or so I’ve been told. I don’t have public git repo of everything because some of it is just private. I don’t even have a public GUI interface for people to file issues on my private code. Public code? Sure, and I use GitHub for it. Personal stuff is not up there, and I don’t care to make it.

    What I do instead is, since I do have Git installed on this server, is allow each user account to make a git repository folder off their home folder. Everyone has ~/repositories/ and in there they can store their code!

    Here are the ones for mine:

    ~/repositories/ipstenu-code.git/
    ~/repositories/ipstenu-mu-plugins.git/
    ~/repositories/mothra.git/
    ~/repositories/scripts.git/
    ~/repositories/slides.git/
    

    The two that start ‘ipstenu’ are for the website ipstenu.org and all it’s children. Mothra is some server scripts I want to keep backed up, scripts are user scripts, and slides are my slides.

    But how do I get there, and how do I keep everything synced up? First is the basic setup for git:

    cd ~/repositories/
    mkdir projectname.git
    cd projectname.git
    git --bare init
    

    From here it’s a simple git clone, too:

    git clone user@example.com:/home/user/repositories/projectname.git
    

    But… I have that project named ipstenu-mu-plugins. When I’ve checked in code, do I manually copy the files over? Of course not.

    When you go into that git folder where I ran the init, you see this:

    [~/repositories/ipstenu-mu-plugins.git]# ls
    ./  ../  branches/  config  description  HEAD  hooks/  index  info/  objects/  refs/
    

    If you go into the hooks folder, you get a list of files:

    ipstenu@ipstenu.org [~/repositories/ipstenu-mu-plugins.git/hooks]# ls
    ./                      commit-msg.sample   pre-applypatch.sample      pre-push.sample
    ../                     post-update         pre-commit.sample          pre-rebase.sample
    applypatch-msg.sample  post-update.sample  prepare-commit-msg.sample  update.sample
    

    You’ll notice I only have one file that isn’t a .sample: post-update

    That’s my secret sauce.

    #!/bin/sh
    export GIT_WORK_TREE=~/public_html/wp-content/mu-plugins
    git checkout -f master
    

    This just uses git checkout, forces the master branch, and dumps the files where I want them. I set it up for each repo when I’m ready to start deploying, and then my dev process is this.

    1. Pull master and all remote branches to make sure I’m up to date
    2. Make a new branch to develop
    3. Push the new branch to origin when I’m sure it’s right
    4. Merge the new branch into master
    5. Push master

    And in that moment, the push will copy my files live.

    Since I don’t ever do dev work in master, this is safe for me. It’s five steps, but I actually have a script to run that first one every single day, so that’s almost step zero. When I work with other people, I always make a backup local branch of master as ‘last known good’ just so I can roll back fast if I’ve been phenomenally stupid. This is usually a date like “GOOD_20141117”, which I know is different from my actual release labels, that are always “REL_1.2.3” style. If it’s a weird thing, like when I was folding Ninja Forms in my site, it was “NINJAFORMS_1.0” because I wanted to be clear what that dev branch was for.

    The Master Race - Doctor Who

    By the way, if you need to set up a shared repository, you should read Kovshenin’s “How To Create a Remote Shared Git Repository”. I don’t, since everyone logs in using SSH keys to the account (so on my shared project, everyone uses ssh projectaccount@projectdomain.com) since they actually need that access anyway.

  • jQuery Toggling

    jQuery Toggling

    I was working on some basic code where I wanted a div to show or hide based on a link. This is simple stuff, but it took me a while to remember it since it’s actually baked into MediaWiki (where I normally use it).

    First up is my HTML code:

    		<h2 class="suggestions-header"><a href="javascript:toggle_visibility('suggestionscontainer');">Suggestions? Click Here!</a></h2>
    		<div style="display:none;" class="sugestions-container" id="suggestionscontainer">
    			<p>I will display when clicked!</p>
    		</div>
    

    Like I said, this is basic stuff. I can get more into it and do things like change the text of the title when you click, but for now this suffices.

    Now for the jquery:

    /**
     * Custom jQuery to toggle visibility
     */
    jQuery( document ).ready(
    
    	function toggle_visibility(id) {
    	       var e = document.getElementById(id);
    	       if(e.style.display == 'block')
    	          e.style.display = 'none';
    	       else
    	          e.style.display = 'block';
    	}
    );
    

    This code got tossed into a toggle.js file and then enqueued with wp_enqueue_script, with a jquery dependancy. Done and done.

    I’m sure this could be done with pure CSS, but I believe in release and iterate.

  • Mailbag: .htaccess Magic with Subdomains and Subfolders

    Mailbag: .htaccess Magic with Subdomains and Subfolders

    From Ginger:

    Hiya, I enjoy your blog and humor within

    In case you still do posts from the “mail bag” — I have seen mention of .htaccess on your site and I’m curious how it relates to the subject of redirects. For example, in my day job we have a site that has two ways to access an external support site.

    So, we want to redirect: www.example.com/support and support.example.com to the same external support site. In the past, I would go to our host and edit the DNS to redirect on these URLS to the external site. Is that the best way or should I be handling this in the .htaccess file now that we’re on WordPress?

    Depends on how lazy I am.

    DNS is great because I can just send support.example.com over, but this only works if the external site lets me do that. I can point my domain at tumblr.com all I want, yet until I add my custom domain to their settings, the URL won’t work. This is why your domain mappings in Multisite don’t always work, folks. You have to tell WordPress, the name servers, and the server that the domain lives there. If you can? Super simple for the subdomain, but not for the subfolder.

    Which brings us to .htaccess:

    Apache 2.2

    RewriteCond %{HTTP_HOST} ^example\.com [NC]
    RewriteRule ^support(.*)$ http://supporturl.com/ [L,R=301]
    
    RewriteCond %{HTTP_HOST} ^support\.example\.com [NC]
    RewriteRule ^(.*) http://supporturl.com/ [L,R=301]
    

    Apache 2.4

    <If "%{HTTP_HOST} == 'example.com' ">
    	RedirectMatch ^support(.*) http://supporturl.com/
    </If>
    
    <If "%{HTTP_HOST} == 'support.example.com'">
    	RedirectMatch (.*) http://supporturl.com/
    </If>
    

    Now someone will note that specifying the HTTP_HOST for example.com is silly, but I disagree. This lets me use http://foo.example.com/support/ to redirect somewhere else. I don’t worry about the www part because I always force no-www on all my domains. Saves me steps later.

    Oh and I’m glad Ginger likes my humor. I don’t know how to turn it off!

  • TotalSpaces

    TotalSpaces

    For everyone at WCSF who asked “How did you get your Spaces on Mac to have names?” here’s the answer.

    TotalSpaces 2, by Binary Rage, is “the ultimate grid spaces manager for your Mac” and they’re not wrong. It took me a long time to agree that I needed to utilize spaces on my Mac, but as I started to want to isolate windows to concentrate (and turned off a lot of notifications), I realized that everything in one ‘space’ wasn’t a great idea.

    I sat down and broke out my spaces into what I frequently do:

    • WordPress
    • DreamHost
    • coding
    • writing
    • being social
    • watching movies

    There is some overlap of apps, but in order to make my life easier, I use Chrome for DreamHost and Chromium for ‘WordPress’ (i.e. me) with separate user accounts in Chrome(ium). That way they can sync between users. I made eight spaces and assigned various apps to only open in those spaces, which is why my screen bounces between spaces when I boot up my laptop. This works fine for me, I just don’t look at it for the 4 seconds it takes for an SSD to boot.

    Allocating what apps open where

    The only issue that remains is that sometimes I want multiple apps in multiple spaces, like a web browser. I have Chromium set to ‘Ipstenu’ but I also want it over in my IRC/Slack window, so I can poke things while I talk in meetings. Right now I just tossed one browser window over there, but I wish I could designate an app to be in only two specific spaces at a time.

    I do keep some apps, like BBEdit, set to ‘all spaces’ for that, but that makes it a little weird as it means that window is open in all spaces. The alternative to that is ‘none’ which I use for iTerm2 to have an SSH window for each space.

    TotalSpaces2 has a free trial, so I advocate people test it and use it to see if it helps their flow. It made mine perfect for my brain, which was the most important thing for me.