Referencing directories in WordPress themes

I needed to enqueue a handful of scripts and stylesheets in a WordPress theme and ran into much confusion between which functions to use to return what paths from the parent theme vs. the child theme. To save myself later here is the breakdown of when to use what. Basic gist is that “stylesheet” will get the child theme. “template” will get the parent.

If you don’t have a child theme any of these will get the current theme.

Absolute Path

These functions get the absolute path on the server’s file system. Mostly useful for referencing other PHP files within your theme’s PHP files:

get_stylesheet_directory() – absolute path to the current theme. If you’re using a child theme it’ll get it. Documentation.

get_template_directory() – absolute path to the parent theme. Even if you’re using a child theme it’ll get the parent. Documentation.

Directory

These functions get the public URI for the theme directory. Useful when you’re trying to publicly display something on the site through your theme files:

get_stylesheet_directory_uri() – returns a properly formatted URI for the current theme. Use if you have a child theme that you want to return. Documentation.

get_template_directory_uri() – returns a properly formatted URI for the parent theme. Even if you’re using a child theme it’ll get the parent theme. Documentation.

From Hugo to WordPress

There are a million and one blog posts for “move from WordPress to Hugo!” out there. This is the opposite of that.

Hugo is good

I like Hugo a lot. If you need a static site generator I’d recommend it without reservation! Once I had it going it worked very well. I loved how fast Hugo could build the entire site and it required almost no server resources. Turns out, you don’t need that much raw computing power to serving static files to a handful of folks every day.

Posting though

But…posting was far more complex than I wanted it to be. In the end I was syncing a folder via dropbox, committing my code to a repo, pushing it to a repo on the server. From there a git hook would run to build the site and then move the files to a folder. Extremely cool and extremely obtuse. If I had just one computer it wouldn’t have been that big of a deal to continue on; however, because I’m a glutton for complication, I bounce between 5 different devices (3 macs, 2 iOS devices) within the course of a week.

Having a web interface to log into matches my mental model of “I am writing and publishing” much better. I also dearly appreciate having drag and drop image support as well as WYSIWYG formatting options. Hugo’s support for non-text media is lacking. That’s totally okay! But, I was finding that I was avoiding publishing certain kinds of posts because I was lacking easy tools to do so.

WordPress and Gutenberg

What finally pushed me to make this change was a recent experience building a new website for Workantile. During that redesign we relied on the Gutenberg editor for formatting our pages. I was impressed! You can create fairly complex pages quickly with blocks in a way that just wasn’t easily doable a few years ago without diving deep into theme files. We’re in a bit of a rough transition point going from the classic editor to Gutenberg (and more importantly the concept of Blocks). It’s getting better all the time though!

Problems

The move went pretty well for the most part. Some technical issues I ran into:

RSS Importer

The RSS importer that is built into wordpress needs some serious attention. The biggest issue is that it fails because it’s calling a deprecated PHP function. The fix for this for me was to comment out the offending line. This StackOverflow post was helpful:

php – Call to undefined function set_magic_quotes_runtime() – Stack Overflow

I just found line 72 in the importer and commented it out. I wouldn’t rely on this edit for an import where you didn’t control all of the content, or as an importer you run more than once. It’s a brittle fix to say the least. Here’s the error and stack trace:

An error of type E_ERROR was caused in line 72 of the file /var/www/beta.chrissalzman.com/wp-content/plugins/rss-importer/rss-importer.php. Error message: Uncaught Error: Call to undefined function set_magic_quotes_runtime() in /var/www/beta.chrissalzman.com/wp-content/plugins/rss-importer/rss-importer.php:72
Stack trace:
#0 /var/www/beta.chrissalzman.com/wp-content/plugins/rss-importer/rss-importer.php(178): RSS_Import->get_posts()
#1 /var/www/beta.chrissalzman.com/wp-content/plugins/rss-importer/rss-importer.php(204): RSS_Import->import()
#2 /var/www/beta.chrissalzman.com/wp-admin/admin.php(344): RSS_Import->dispatch()
#3 {main}
  thrown

Hugo’s RSS Implementation

And on the Hugo end of things: Hugo’s built-in RSS generator doesn’t include the full text of the posts. It also doesn’t include categories. I happen to be the sort of person who likes adding categories, so this was a problem! Here’s a gist of my RSS theme file that has the full text and categories:

Hugo RSS Implementation with Categories · GitHub

This looks for the categories set in the frontmatter of your markdown files. If there are none it skips it and nothing is added to the feed for that post.

RSS Redirect

I wanted to make sure anyone who subscribed to my old RSS feed continues to get the new one. To do so I set up a 301 redirect using this plugin:

Simple 301 Redirect

Keeping it around since it’s always nice to have this in a readily accessible place.

Images

Moving images over to the new site involved making sure they were uploaded appropriately to WordPress’ Media library. I toyed with the idea of doing one big import and going through and fixing individual images. Then I found this plugin that just did it for me. Installed it and then Edited all of my posts and resaved them. It ran through and copied everything over and updated the src tags for me:

Auto Upload Images – WordPress plugin | WordPress.org

Inserting images in Hugo was one of the reasons I wanted to get away from it so this was nice to have it just work. After I ran this I turned it off.

Conclusion

So far, so good. I’m happy with this and this post was fully written and edited in the WordPress editor. It’s nice to have “my website” compartmentalized to something I go to on the internet to edit, although I will miss how much posting a blog post made me look like I was attempting to hack the planet.

Some Thoughts on Tools

Here is what I’ve been learning about tools:

  • Become enamored with taking care of your tools not buying new ones.
  • Buy the cheapest tool you need for a job. If it breaks or fails its intended purpose then buy a more expensive replacement.
  • Completing a project from start to finish is the only way to see what tools you actually need. Planning is fraught with false assumptions.
  • Youtube tutorials are a useful fiction. Watch them for techniques and explanation yet understand that the moments they don’t show are where all the laborious and detailed work is happening.
  • Avoid forums where people argue about specifications and not real world results.
  • If you are scared of the next step, practice it at a smaller scale. If you are still wary, talk it through with a friend.
  • Modify your tools to suit your purposes.
  • Be generous with your tools. Especially those that spend most of their lives sitting on a shelf.

How I Spent My Friday Night, or Why Framerate is the Wrong Choice for Managing Time-based Animations, Actions, and Effects

Of the bugs I have written a lot the one that keeps biting me is improperly locking an animation, effect, or action to the framerate of the game rather than to an elapsed time on a clock. You can never depend on your game running at a specific and consistent framerate across every device it’ll get played on. This seems obvious, but is a very easy assumption to make when you’re in the thick of it. If a device slows down, or speeds up, suddenly that tuned animation that elapsed over the course of 60 frames might take 2 seconds to complete.

For a background animation this might be fine and this isn’t necessarily that bad. However, what if it’s a function that the user is relying on for either visual feedback, or to take their next action?

That’s bad.

The Dark Souls of This Bug

There was a bug in Dark Souls 2: Scholar of First Sin in which character equipment was breaking very fast on the PS4. Equipment in that game has a durability rating that goes down as you use it. If you go too long without repairing it it will break.

Turns out, they’d linked that decrementing of durability to the framerate. On the PS4 the game ran at a nice steady 60 frames per second and thereby was resulting in equipment breaking very fast.

Thankfully we have this lovely bit of honesty from the patch notes:

“Fixed issue whereby weapon durability was decreased drastically when used on enemy corpses, friendly characters, etc. (Especially apparent for users running the game at 60 fps as the durability decrease rate was linked to the frame rate).”

Source: IGN

Scope Creep Studios is Not a AAA Studio, but We Have Similar Problems

A common way that I’ve introduced these problems is by doing something like the following:

public IEnumerator moveItOverSome() {   
    while (gameObject.transform.localscale.x >= 0f) {
        gameObject.transform.localscale -= new Vector3(.1f, 0f, 0f);
        yield return null;
    }
}

Every frame the Coroutine is running you shrink the scale of the object a tenth of a unit until it’s below 0, which functionally means that it’s invisible. Please ignore the other four or five problems with that coroutine. I’m going for simple readability right now.

The issue with this is twofold:

  • If your framerate dips or spikes or whatever the movement isn’t going to work as expected
  • Coroutines sometimes don’t behave exactly how you want them to

Give me a specific example, please

We were running into an issue on our upcoming app, Night Lights: A Toddler Toy, where every once in a while the coroutine to shrink our object refused to add the Vector3 how we wanted it to be added. This would result in the coroutine running for seemingly forever as it slowly decremented the size of the object by .0000001f every frame, or it’d shrink part of the way and then get caught somewhere and looked to be about half the size it should have been or looked like a speck, or generally just wasn’t what we wanted.

After a lot of hours debugging—_a lot of hours_—we finally stopped and did what we should have done from the start: wrote the corotuine to shrink from it’s full size to 0 over the course of 1 second using a lerping function.

Lerping interpolates between two values based on a third value between 0 and 1. Roughly: how far along in this process am I? At the start: 0, at the end: 1. Unity includes a Lerp method that returns a Vector3.

For the coroutine then we need to note the values we want to go between and the start time and then every frame the coroutine runs we can determine how far along we are in the shrink.

To whit:

public IEnumerator shrink() {
    Vector3 startSize = new Vector3(2f, 2f, 1f);
    Vector3 endSize = new Vector3(0,0,1f);

    //When does all this start?
    float movementStart = Time.time;

    //While current time is less than when we started
    //Plus how long we want it to go for (1 second)
    while (Time.time <= movementStart + 1.0f) {

        //Calculate our new size using the current time (Time.time)
        Vector3 updatedSize = Vector3.Lerp (startSize, endSize, (Time.time - movementStart));

        //Update the gameObject’s size using the new Vector3
        gameObject.transform.localScale = updatedSize;
        yield return null;
    }
}

To the toddler both approaches—when they work—visually look similar. Our latter example is reliable though and thereby the better solution for our needs.

A Note About Toddlers Tastes for Bugs

We found in testing that toddlers often like it when the app breaks in strange ways, but they also tend to then want it to rebreak in those exact same ways again, which is hard to do.

If you’ve spent any time with toddlers that will not surprise you in the least.

What Did You Learn?

Tozier reminded me what’s really important in life when I subtweeted the very short version of this blog post:

“Imagine how much you’re _learning_ though!”

Here’s what we learned:

When it comes to determining how something happens over time in your app or game you need to tie that action to some sort of timer. That timer could be the framerate, system time, game time, a clock in your basement that you have a webcam pointed to, or something else. Unless there’s a strong reason to do so one should reference a clock that isn’t tied to system performance.

Jekyll to Hugo Along with an Updated Deployment Script

I moved my blog from Jekyll to Hugo because I can’t leave well enough alone.

Jekyll is wonderful, it’s also slower than it should be for building a site. Not like “go get some coffee” slow, but building felt sluggish. I also needed to reconfigure my workflow for publishing anyway. My earlier workflow involved running Jekyll client-side, keeping the resulting _site folder in version control and deploying that.

Trust me, it made a lot of sense when I was setting it up. However, it quickly started to show its fragility.

My primary goal was to have the server generate the site itself so I needed to start from scratch anyway. This seemed like a good opportunity to try Hugo. I also wasn’t running ruby on my webserver yet and, frankly, installing Hugo was a lot easier than the full ruby setup:

sudo apt install hugo

And that was about it for setup on the server.

Hugo and Jekyll both use markdown files to generate the site and their frontmatters are similar enough that the transition to Hugo was incredibly simple.

Fast forward through a lot of futzing with config files, themes, and testing builds.

I eventually landed on this: I keep the project in version control and .gitignore the exported site from the repo. The site can still be built locally if needed with hugo serve but when the project is commited it ignores the exported site. After the commit is pushed to the server it runs the following post-recieve hook:

#!/bin/sh
#Checkout the repo to a temporary build folder
git --work-tree=/var/repos/hugoblog/tmpbuild/ --git-dir=/var/repos/hugoblog/ checkout -f
#Build the site
hugo -s /var/repos/hugoblog/tmpbuild/
echo "\n\nBlog has been built. Moving it to chrissalzman.com/blog\n\n"
#Then move the public folder to the right place
rsync -r /var/repos/hugoblog/tmpbuild/public/ /var/www/chrissalzman.com/blog

Nothing terribly fancy and this will likely get modified into the future. It checkouts the project to a folder, runs Hugo, tells me it worked, then moves it over with rsync.

Note

I did run into a theme issue with git that stumped me for a bit. The theme was cloned in using git. Since it had its own git repo it wasn’t getting tracked by the project’s git repo. After pushing it to the server hugo was generating a blank site since the theme was blank.

My fix was to copy/paste the theme into a differently named folder, update config.toml to that theme folder, and then add another commit. After that it worked. I’m sure this is the sort of thing that could be solved leveraging git in some way I don’t quite understand, but this was easier for me. I also anticipate designing my own theme.