Make Advanced Custom Fields smarter about handling date fields

I love Advanced Custom Fields almost as much as I love WordPress itself. But that’s not to say it doesn’t have its problems. Most are obscure, and minor… and incredibly aggravating once you stumble upon them.

Here’s one such case. Date Picker fields are great, but no one seems to be able to agree on how to store dates in a database… other than insisting on avoiding Unix timestamps, the obvious choice.

ACF stores its dates, for some reason, in YYYYMMDD format (or, as we’d express it in PHP Land, Ymd). No delimiters at all. If you’re not going to use Unix timestamps, why not at least use the MySQL convention of Y-m-d H:i:s? But I digress.

I’m presently working on a project that merges some functionality of ACF and Gravity Forms, along with some custom code, to create a jobs board. It’s super-slick how Gravity Forms can create posts from a form submission, and even set them to pending review so a site editor can come in and review them before publishing.

But… dates. Jobs boards have a lot of dates. And while Gravity Forms offers a wealth of options for date string format, Ymd isn’t one of them. So it ends up storing the date value in the database in a format ACF doesn’t like. Because ACF is very picky. It wants that format, and no other. If the value in the field is not in Ymd format, the value displayed on the admin editing screen is just… blank. And then when you save, whatever was previously saved in that field is erased.

It doesn’t have to be this way. And thanks to the following bit of code, it won’t be. Now bear in mind, this is only altering what ACF renders on the editing screen. Once you’ve saved again from that point, the date will be stored in ACF’s preferred format, but up until then, it will be in whatever other format it was in when it landed in the database.

If you’re writing your front end code proactively, that won’t matter. Because you’re already assuming data inconsistency and using strtotime() to standardize any dates you’re working with in your templates, right? Of course you are.

OK, then. So the real goal here is just to get ACF to display the correct, saved date when you go in to edit the post, so it doesn’t then wipe out the date when you hit Save Changes.

In your functions.php file, or wherever you think is best (a plugin would be nice), do this:

function acf_smart_dates($field) {
  if ($field['value']) {
    $field['value'] = date('Ymd',strtotime($field['value']));
  }
  return $field;
}
add_filter('acf/prepare_field/type=date_picker','acf_smart_dates');

That’ll do.

Covering Kraftwerk: the process (part 1)

As my Twitter followers know, I’ve concocted a harebrained scheme to record an EP of Kraftwerk covers, using solely the Pocket Operator calculator-esque synthesizers from Teenage Engineering. This project was inspired by my love of Kraftwerk and my assumption that Teenage Engineering was directly influenced by Kraftwerk (especially the song “Pocket Calculator”) in creating the Pocket Operators.

I’m taking a, let’s say, judiciously-paced approach to this project. Partly because I don’t have a lot of free time at the moment, and partly because I need to let this thing fully gestate in my brain. Also because I’m still learning how the Pocket Operators work. They’re ingeniously designed, but not exactly intuitive. (Then again, I don’t find any electronic devices besides computers intuitive. Let’s not even get started on fax machines.)

I’ve identified the four Kraftwerk songs I want to cover:

  1. Ruckzuck (1970)
  2. The Man-Machine (1978)
  3. Pocket Calculator (1981)
  4. Tour de France, Étape 1 (2003)

My first baby steps into the project were in the form of some brief tinkering with the Pocket Operators themselves to lay down the basic foundation of “Ruckzuck”, which I did from memory. (It was easy to do this one from memory; after all, I watched a lot of Newton’s Apple as a kid.) I commemorated this with a brief video posted to Instagram:

A video posted by Scott Anderson (@room34) on

This past weekend I took my second step, which went a bit further. I have decided that part of what is challenging to me with playing these Kraftwerk songs (as simple as they are) on the Pocket Operators is that I don’t have any written music to work from. So I’m introducing a second step in the process, but one that will not at all make its way into the final product. I’m creating versions of the songs entirely with software instruments in Logic Pro X, just so I have my own transcriptions (really, adaptations, because I’m not trying to get it perfect) to work from when I program the Operators.

Here we have the beginnings of my rough Logic Pro X interpretation of “The Man-Machine.”


I am excited about this project! Just hoping I can find some time in the near future to keep pushing it forward.

What will the end results be? I’m not sure. While I’ve dabbled with recording covers before, I’ve never taken them through to completion and released them into the world. I’m not even sure how I want to go about that. But so far it’s still a long way off.

Hack your hosts file to prevent distracting yourself at work

I suppose it’s a significant statement on the increasing marginalization of the computer as a work-only device. I hardly ever touch my Mac at home anymore. I really only use it for work. The problem is, I am permanently logged into Facebook and Twitter on my computer, and I am prone to distraction.

So I made the decision today to further that marginalization, by making it impossible for me to access Facebook and Twitter on my Mac. How? It’s easy! Assuming you have administrator access, at least. But why wouldn’t you? (If your Mac is a company computer and they have things so locked down, I’d say don’t worry about blocking social media sites… spend that time working on your résumé.)

These instructions are for Mac OS X. I’m not really sure how to do this in Windows. (And, honestly, I don’t care.) Instructions for Linux would be fairly similar, but you’d do it in a Terminal window and there’d be some sudo involved. (Actually, you can do that on a Mac too. I’ll give those instructions at the end.)

Now then. Open a Finder window and press Command-Shift-G. In the box, type /etc/hosts and click Go.

Screen Shot 2015-11-12 at 7.58.15 AM

This will take you to the “hidden” /etc directory (part of the Unix subsystem) and highlight the hosts file, which is what you need to edit.

But, you can’t do it here.

Files in the /etc folder are write-protected, but if you copy it to your desktop, you can edit it. So, drag it to the desktop. (Note that since it’s a protected system file, just dragging it to the desktop will make a copy, rather than moving it.)

Double-click the hosts file on your desktop. It should open in TextEdit. (If you’re asked to pick a program, pick TextEdit.)

Place the cursor at the bottom of the file and add these lines:

127.0.0.1 facebook.com
127.0.0.1 www.facebook.com
127.0.0.1 twitter.com
127.0.0.1 www.twitter.com

So what’s happening here? Well, the numbers are IP addresses, which are the true addresses of every device connected to the Internet. Domain names (like twitter.com) are essentially “aliases” for IP addresses. Normally your computer connects to a DNS server on the Internet to look up these associations. But before it does that, it checks this hosts file. If a domain is in there, it doesn’t bother checking any further. And 127.0.0.1 is a special IP address associated with the fake domain name localhost — basically, it’s the computer’s self identification on the Internet. “Me” in other words.

There’s probably no web server running on your computer, so loading http://127.0.0.1 in a web browser will return… nothing. But even if you do have a web server running on your computer, it’s not Facebook or Twitter, so mission accomplished.

All right. Now that we have the hosts file updated, save it, and then drag it back into the /etc folder. You’ll get a stern warning from the system.

Screen Shot 2015-11-12 at 8.06.50 AM

Click Authenticate. That gives you another annoying, but smaller, alert.

Screen Shot 2015-11-12 at 8.08.13 AM

Click Replace. Now you have to enter your administrator username/password. Do that then click OK.

Screen Shot 2015-11-12 at 8.09.15 AM

You’re done. (And note this time it moved the file from the desktop back into /etc. It doesn’t copy it like it did when you moved it to the desktop.) Now try loading Facebook or Twitter in your web browser!

Screen Shot 2015-11-12 at 8.11.22 AM

Want to do all of this at the command line instead? It’s actually a lot easier, now that I think about it. These instructions should work for either Mac or Linux. Open a Terminal window. Type sudo nano /etc/hosts and hit Enter. Move the cursor to the bottom of the file and enter the lines I gave earlier. Press Ctrl-X then Y to save your changes. That’s all! Seriously!

Note: If you’re on IPv6 (if you even know what that is), you may want or need to use ::1 instead of 127.0.0.1.

Q: Should I build an app? A: Probably not.

One of Room 34’s long-time agency partners emailed me today asking if we build mobile apps. It was a simple question. The email itself was only one sentence, and, initially, so was my response:

We haven’t yet, but it’s been on my radar to potentially pursue.

Then I gave it more thought, and realized I should flesh out that answer a bit, with an explanation of why we haven’t developed any apps. Yet.

Honestly I’m sure part of the reason is that we’re a web development shop. That’s what we do. I’d be lying — to myself — if I didn’t acknowledge that there’s some amount of a desire to “protect my territory”; apps are a threat to the web development business. Adapt or die, etc. But I think apps have been around long enough now to show the web isn’t going to die. The nature of the web and how we use it is changing, but the web itself is still a huge part of the Internet experience, and its underlying technologies (HTTP, SSL/TLS, XML, and JavaScript or JavaScript-derived tools like JSON and AJAX for sure) are fundamental to how any Internet-connected mobile app works!

Yet, I still make the argument that a lot of people who think they need an app really don’t. All they need is a mobile-friendly (ah-hem, responsive) website. So that was the rationale I laid out in the rest of my email response:

Most of the time when people have approached us about an app, I have convinced them that it didn’t make sense for their needs to do an app. But there are definitely legitimate uses.

A few reasons not to do an app, and just do a mobile website instead:

  1. Apps are more expensive to develop.
  2. Apps require more promotion to achieve awareness.
  3. Users have to make the choice to seek out the app in the App Store / Google Play and download it.
  4. Often client requirements for the app don’t involve anything a mobile website can’t do.

On top of those reasons, #2, and to some extent #3, generally means you need a marketing website to promote the app anyway, and if the user is already coming to the website, if #4 applies, there’s really no value left in creating the app, unless it’s a paid app or has ongoing in-app purchases to achieve any kind of ROI.

Reasons to create an app:

  1. Advanced features that require native device functionality, that a website can’t achieve.
  2. The app itself is a (reliable) source of revenue.
  3. The app is for an industry where it might be preinstalled on users’ devices, or required for their work.

What I didn’t mention is that the app “gold rush” is over. The potential in 2015 of a new venture to get rich with an app is approaching the odds of winning the lottery and getting struck by lightning simultaneously.

The only reason to create an app now is if it’s filling a genuine need that can’t be met with a mobile website, and it has the necessary value to the end user that the higher barrier of entry into using an app, compared to a website, can be overcome.

The simple way to add a “force SSL” option in WordPress

There are plugins for just about everything in WordPress. But cluttering up your site with plugins isn’t always such a great idea. They add bloat that can slow down your site, and if poorly written can cause potential conflicts.

Plus, a lot of them are simply over-engineered. I hate that.

That said, I love good plugins, especially Advanced Custom Fields by Elliot Condon. I consider it essential to every WordPress site I build… which is a lot these days.

A site I’m currently working on has some pages that require SSL encryption. And I want the client to be able to turn SSL on or off on a per-page basis. But I didn’t want to use a plugin (besides ACF) to do it. [Disclaimer: you don’t actually need to use ACF for this; the standard Custom Fields capability will do.]

Before getting started, make sure your site actually has an SSL certificate installed and properly configured. And for this to work as shown, the cert needs to use the same domain name as the site itself. If it’s different, your redirect URLs will be a bit more complicated and will require some customization of this code, but it’ll still work.

First, set up your custom field. I’m using force_https as the field name, but it can be whatever. Make it a True/False field. (If you’re not using ACF, just remember you’ll be entering 0 or 1 as the value.)

Next, in your functions.php file, add the following:

add_action('template_redirect', 'my_force_https');
function my_force_https() {
  if (is_ssl()) { return null; }
  global $post;
  if (!empty($post->ID)) {
    if (!empty(get_field('force_https',$post->ID))) {
      $ssl_url = str_replace('http://','https://',get_the_permalink($post->ID));
      wp_redirect($ssl_url); exit;
    }
  }
  return false;
}

Picking this apart: We’re using the template_redirect hook. By this point the post has been loaded. We have all of the data we need, and it’s kind of our “last chance” to get WordPress to do a redirect before it starts rendering the page.

First we run the built-in WordPress function is_ssl(), because if we’re already on an SSL connection, there’s nothing to do. (And, if we didn’t do this check, we’d create a redirect loop.)

Next, if we have a post ID, we use the ACF function get_field() to check whether the force_https custom field is checked for this page. If it is, then we modify the page’s permalink to start with https:// and trigger the redirect. That’s it! [Note: If you’re not using ACF, you’ll need to use the built-in WordPress function get_post_meta() instead of get_field().]

Of course, that’s not quite it. You may notice after you have this working that your page loads with an https:// URL, but you’re still not getting the reassuring lock icon in your browser’s address bar. What gives?

Well, that’s because you probably have assets in the page that are loading over a non-SSL connection. In my experience, this is almost always because of images in your content that have a full, non-SSL URL. Browsers won’t give you the lock icon unless every asset on the page was loaded over an SSL connection.

So I’ve added this second function that strips the protocol from any instance of src="http://... in a text string. If you’re not familiar with “protocol-less” URLs, modern browsers allow you to omit the protocol — http:// or https:// — from URLs in your HTML, using just // instead, and the browser will automatically handle those with the same protocol used to load the page.

Using the filter the_content, this will automatically get applied to most page content and you’ll probably be good.

add_filter('the_content', 'my_strip_protocol');
function my_strip_protocol($content) {
  if (is_ssl()) {
    $content = str_replace('src="http://','src="//',$content);
  }
  return $content;
}

If you add this and you’re still not getting the lock, it means you probably have <img> tags within your theme that include full non-SSL URLs, or possibly some CSS or JavaScript assets that are being loaded over non-SSL connections. You’ll have to troubleshoot that yourself, but with the developer tools built into modern web browsers, that shouldn’t be too difficult. Remember, now that you have it, you can always use this my_strip_protocol() function directly in your theme files as well.

Just a side note about one of my idiosyncratic coding conventions: I always use !empty() when checking for a value that evaluates to true, but you don’t have to. It comes from my prior experience working with CakePHP. The benefit is that you won’t trigger any PHP warnings if the variable you’re evaluating hasn’t been declared.