Page Links To v3.0

Today I pushed an update to my redirect and repointing plugin, Page Links To. Tomorrow, this plugin will have been in the WordPress.org Plugin Directory for 13 years (it was the 339th plugin in the WordPress plugin repository; there are now over 75,000!).

To celebrate its transition to a teenager, I’ve added some new features and UI enhancements.

Last month, I received survey responses from over 800 Page Links To users and learned a lot about how it’s being put to work. One of the most interesting things I found was how many people are using it for URL redirects. For example, they might have a really long URL on their own site or someone else’s site that they want to be nice. example.com/summer-sale instead of example.com/store/specials.aspx?season=summer&_utm_source=internal. But in order to create these redirects, you have to go through the cluttered and sometimes slow post creation screen. All you really need to create a redirect is a title, a destination URL, and a local short URL.

You’ll now find a menu item “Add Page Link” that will allow you to quickly add a redirected Page without having to wait for the entire WordPress post editing interface to load. It’s super fast, and it doesn’t redirect you away from the screen you’re on.

Since short URLs are better for sharing (and remembering), the UI will give you a little push to shorten the URL if the one generated from your title is too long. From there, you can Save Draft or Publish.

Hey, that URL is getting a bit long
Custom slug, for a better short URL

Additionally, this release includes a “link” indicator on post and page list screens, so you can easily see what items have been re-pointed with Page Links To. When hovered, the link icon will reveal the destination URL for a quick view.

The “link” icon means that this item has been pointed elsewhere.

If you want to grab the “local” short URL (which will be redirected to your chosen URL when someone visits it), just click “Copy Short URL” from the actions, and it’ll be in your clipboard.

Hover the “link” icon to see where it’s pointing.

That’s it for version 3.0, but I’ll have more to announce soon — stay tuned!

Making ScoutDocs: Build Tools

Continuing my series about ScoutDocs and the process of building it, this week I’m talking about Build Tools.

ScoutDocs-plugin-header-1544x500What is ScoutDocs? ScoutDocs is a WordPress plugin that adds simple file-sharing to your WordPress site.

Coding in React involves JSX, a bizarre-but-wonderful XML syntax that you dump directly into the middle of your JavaScript code. It feels exquisitely wrong. Browsers agree, so your JSX-containing JS code will have to be transpiled to regular JavaScript. This can involve using a complex maze of tools. Babel, NPM, Webpack, Browserify, Gulp, Grunt, Uglify, Uglifyify (yes, you read that right), and more. You have decisions to make, and you will find fierce advocates for various solutions.

For ScoutDocs, I decided to go with Grunt for task running, because I was already comfortable with it, and I needed it for grunt-wp-deploy. Use a task runner you are already comfortable with. Even if it is just NPM scripts. You’re learning a lot of new things already. It’s okay to keep your task runner setup.

Next, I had to choose a JS bundler which would let me write and use modular code that gets pulled together into a browser-executable bundle. After deliberating between Webpack and Browserify, I chose Browserify. Webpack is really complicated. It is also very powerful. I recommend you avoid it until you need it. I haven’t needed it yet, and found Browserify to be easier to configure and use, even though it’s a bit on the slow side.

As I was building ScoutDocs and tweaking my dev tools, tweaking my Grunt file, and writing code to search/replace strings etc, I began to feel like the time I was spending too much time on tooling. Was I becoming one of those people who spend all their time listening to productivity podcasts instead of… being productive? I can see how someone could get sucked into that trap, but putting a reasonable amount of time into configuring your development tools can pay dividends for you beyond simply the time saved. It can also prevent mistakes, keep you in coding mode more often, and increasing your confidence in your code builds. Spend the time up front to make your tools work for you.

Other posts in this series:

 

Making ScoutDocs: React

Continuing my series about ScoutDocs and the process of building it, this week I’m talking about React.

ScoutDocs-plugin-header-1544x500What is ScoutDocs? ScoutDocs is a WordPress plugin that adds simple file-sharing to your WordPress site.

After the first iteration of ScoutDocs was built and none of the partners on the project were happy with its experience, it became clear that in order to deliver a clean, simple interface for file uploading and sharing we needed to leave the bounds of the WordPress admin. It didn’t take me long to decide that React would be the tool I used to build the new interface.

There is an incredible momentum behind React, and a rich ecosystem of libraries, tools, and educational resources. But beyond all that, React is just plain fun to code. Once you accept the central premise that a view layer and the controller that handles that view are inextricably linked, and once you get over the weirdness of quasi-HTML-in-JS that is JSX, coding in React is a joy.

Screen Shot 2018-06-10 at 10.19.07 PM.png

Make no mistake, learning React is not a weekend project. It will take a while before it feels like home. But once you get it, you feel very powerful.

The first lesson I learned was don’t learn React by rewriting your app in React. I tried this. I read some tutorials about React and it felt straightforward, and I was like “let’s do this.”

confused.gif

This was a bad idea. I was overwhelmed. I had no idea where to start. Next, I tried following some of the interactive tutorials that required me to build a simple React app and then slowly add functionality to it, refactoring it multiple times, until I understood not just the code that I ended up with, but the process of creating it. This went much better.

Start small, and build a bunch of “toy” apps before you use React for your own apps. Once you are able to “think in React”, you’ll be nearly physically itchy to go re-code your app in React, and that’s how you know you’re ready. If you jump the gun, you are going to get stuck a lot, and it will be frustrating.

As you learn React and explore the React ecosystem, you will likely hear about Redux, which is a system for storing application state, and is commonly used with React apps. It looked complicated, and even its creator wrote a post saying you might not need Redux. So I skipped it. This was probably the right call when I was starting out. But as I fleshed out the ScoutDocs app and its complexity increased, I ran into a problem.

See, React breaks your app up into these nested chunks of UI and functionality called components. Data flows down through your components. So if a user updates their name, that change will flow down from higher up components like a Page component down to a PageHeader, down to a NavBar, down to a UserStatus. Once this is all set up and you update data in a parent component, the changes automatically flow downstream, and the UserStatus component updates and re-renders. It’s great. Except that there are a bunch of intermediate components that accept and “forward” that user name data to their children, without actually caring about it themselves. When you inevitably refactor something and need to add new data that flows through these components, every single intermediate one needs to be updated to pass it on. It is tedious. You will hate it.

Worse, because events in React flow upwards, if a user updates their name in the UserName component, that change needs to flow up to ProfileForm, up to Profile, up to Page, and then up to your main App component. When you refactor, you need to make sure this event forwarding chain stays connected. Yet more tedium that you will hate.

Redux solves this by letting your React components, no matter how deeply they are nested, subscribe directly to the data they need.

I really wish Dave Ceddia had written this excellent post about Redux two months earlier.

If you have a component structure like the one above – where props are being forwarded down through many layers – consider using Redux.

This is what I needed to hear, and knowing this would have saved me a lot of frustration and time that I now have to spend converting ScoutDocs to use Redux.

Use Redux when your React data flow starts to get unwieldy.

Another mistake I made early on was making the data my React components accepted too restrictive. For example, I wanted the ability to prefix a Row component with a clickable icon. So I let the component accept an icon and onClickIcon property. I just passed a Font Awesome icon name in, and a function I wanted to run when clicked. It worked great.

Screen Shot 2018-06-10 at 10.26.08 PM.png

Then I needed to add a second icon in front, in some circumstances. Ugh. I certainly didn’t want to do otherIcon and onClickOtherIcon. Instead, what I should have done was let the component accept beforeRow which could be anything… like an array of <Icon> components or a single one or even other components altogether.

Screen Shot 2018-06-10 at 10.31.45 PM.png

This can be used for many more situations than the one (“put an icon before the row”) that I’d originally envisioned.

Your React components should be flexible, so they can be reusable.

Other posts in this series:

  • Outsourcing
  • React
  • WordPress Rest API
  • PHP 7
  • Build tools
  • Unit testing

Lessons Learned Making ScoutDocs: Outsourcing

Now that ScoutDocs is in the WordPress plugin repository, I’d like to share some lessons I learned making it. Every project teaches me something — this one taught me a lot.

ScoutDocs-plugin-header-1544x500What is ScoutDocs? ScoutDocs is a WordPress plugin that adds simple file-sharing to your WordPress site. You can upload files (which are stored securely in the cloud and served over HTTPS via a global CDN), and share them with individuals or groups of individuals. Email notifications are also handled by the ScoutDocs service, getting around the issue of reliable email delivery on a shared host. You can require that recipients accept or decline the files you’ve shared, e.g. so you can see which of your employees has seen the new employee handbook. Instead of files living as email attachments (if they even fit) or off on some third-party site, people can access them on your site.

In this weekly series, I’m going to cover:

  • Outsourcing
  • React
  • WordPress Rest API
  • PHP 7
  • Build tools
  • Unit testing

First up, lessons learned about outsourcing.

When we started making ScoutDocs, the question was raised as to whether it would be beneficial to outsource any of the coding. My time was valuable and limited, so I figured that if I had another developer code while I slept, I could spend an hour in the morning reviewing the code and giving them direction for the next workday. I had visions of quickly scanning code while my morning coffee brewed, twirling an invisible moustache, and muttering “good, good.”

This is not what happened.

The issue I quickly ran into was that for any nebulously defined problem, someone else’s solution was unlikely to match what I wanted. Their assumptions would not be the same as mine. As a result, the odds of me being happy with their solution were very low.

I spent a lot of time rewriting code.

And because I was spending all my time “fixing” the code I wasn’t really looking at the product as a whole.

When the contractors were done, my ScoutDocs partners and I looked at it, and we realized that it… was bad. Forget code quality, which despite all my vain reshuffling was still lacking: what we had was just overall a terrible user experience. Rather horrifyingly, we admitted that what we needed to do to give it the user experience we wanted was nothing short of a total rewrite.

demo.gif

I rolled up my sleeves, learned React, and rewrote ScoutDocs until almost nothing of the original code and user experience remained.

So was outsourcing a waste? Not completely. Some code was retained, mostly relating to the Amazon S3 interface. I was glad that someone else had experienced the singular joy of spending an eternity lost in a maze of Amazon Web Services documentation and confusing code samples. Additionally, if I had set out to build the initial version of the code, it would have taken a lot of my time (which I did not have much to spare), and might have meant that our horrifying realization would have been delayed for several months.

Knowing what doesn’t work is valuable, even if you have to throw it away. That’s mostly what we had gotten for our money: figuring out what didn’t work. If outsourcing can get you to these realizations sooner or for less money, it might be well worth it.

As I rewrote the software, my partners asked me a few times if I regretted outsourcing. I didn’t, for the above reason, but also because outsourcing had solved some of the coding issues that would have been a slog for me. However, if I was doing it all over again, I would have done more work upfront to identify specific, well-defined tasks that I wanted to outsource.

Delegation makes sense when the task is well-defined. At the extreme, you could spend so much time redoing work and asking for revisions that you’d have been better off just doing it yourself. If you can specify exactly what constitutes success in a task, and the time it takes you to specify that is much less than the time it would take you to do the task, outsource it.

Check back next week for my thoughts on rewriting ScoutDocs in React.

Handling old WordPress and PHP versions in your plugin

New versions of WordPress are released about three times a year, and WordPress itself supports PHP versions all the way back to 5.2.4.

What does this mean for you as a plugin developer?

Honestly, many plugin developers spend too much time supporting old versions of WordPress and really old versions of PHP.

It doesn’t have to be this way. You don’t need to support every version of WordPress, and you don’t have to support every version of PHP. Feel free to do this for seemingly selfish reasons. Supporting old versions is hard. You have to “unlearn” new WordPress and PHP features and use their older equivalents, or even have code branches that do version/feature checks. It increases your development and testing time. It increases your support burden.

Economics might force your hand here… a bit. You can’t very well, even in 2018, require that everyone be running PHP 7.1 and the latest version of WordPress. But consider the following:

97% of WordPress installs are running PHP 5.3 or higher. This gives you namespaces, late static binding, closures, Nowdoc, __DIR__, and more.

88% of WordPress installs are running PHP 5.4 or higher. This gives you short array syntax, traits, function-array dereferencing, guaranteed <?= echo syntax availability, $this access in closures, and more.

You get even more things with PHP 5.5 and 5.6 (64% of installs are running 5.6 or higher), but a lot of the syntactic goodness came in 5.3 and 5.4, with very few people running versions less than 5.4. So stop typing array(), stop writing named function handlers for simple array_map() uses, and start using namespaces to organize and simplify your code.

Okay, so… how?

I recommend that your main plugin file just be a simple bootstrapper, where you define your autoloader, do a few checks, and then call a method that initializes your plugin code. I also recommend that this main plugin file be PHP 5.2 compatible. This should be easy to do (just be careful not to use __DIR__).

In this file, you should check the minimum PHP and WordPress versions that you are going to support. And if the minimums are not reached, have the plugin:

  1. Not initialize (you don’t want syntax errors).
  2. Display an admin notice saying which minimum version was not met.
  3. Deactivate itself (optional).

Do not die() or wp_die(). That’s “rude”, and a bad user experience. Your goal here is for them to update WordPress or ask their host to move them off an ancient version of PHP, so be kind.

Here is what I use:

View code on GitHub

Reach out on Twitter and let me know what methods you use to manage PHP and WordPress versions in your plugin!


Do you need WordPress services?

Mark runs Covered Web Services which specializes in custom WordPress solutions with focuses on security, speed optimization, plugin development and customization, and complex migrations.

Please reach out to start a conversation!

Updating plugins using Git and WP-CLI

Now that you know how I deploy WordPress sites and how I configure WordPress environments, what about the maintenance of keeping a WordPress site’s plugins up-to-date?

Since I’m using Git, I cannot use WordPress built-in plugin updater on the live site (and I wouldn’t want to — if a plugin update goes wrong, my live site could be in trouble!)

The simple way to update all your plugins from a staging or local development site is to use WP-CLI:

wp plugin update-all
git commit -am 'update all plugins' wp-content/plugins

That works. I used to do that.

I don’t do that anymore.

Why? Granularity.

One of the benefits of using version control like Git is that when things go wrong, you can pinpoint when they went wrong, and identify what code caused the issue.

Git has a great tool called bisect that takes a known good state in the past and a current broken state, and then jumps around between revisions, efficiently, asking you to report whether that revision is good or bad. Then it tells you what revision broke your site.

If you lump all your plugin updates into one commit, you won’t get that granularity. You’ll likely get the git bisect result of “great… one of EIGHTEEN PLUGINS I updated was the issue”. That doesn’t help.

Here’s how you do it with granularity:

for plugin in $(wp plugin list --update=available --field=name);
do
    wp plugin update $plugin &&
    git add -A wp-content/plugins/$plugin &&
    git commit -m 'update $plugin plugin'
done;

This code loops through plugins with updates available, updates each one, and commits it with a message that references the plugin being updated. Great! Now git bisect will be able to tell you which plugin update broke your site.

And what if you can only run WP-CLI commands from within a VM, and Git commands from your local machine? For instance, if you’re using my favorite tool, Local by Flywheel, you have to SSH into the site’s container to issue WP-CLI commands, but from within that container, you might not have Git configured like it is on your host machine.

So what you can do is break the process into two steps.

On the VM, run this:

wp plugin list --update=available --field=name > plugins.txt
wp plugin update-all

That grabs a list of plugins with updates and writes them to a file plugins.txt, and then updates all the plugins.

And then on your local machine, run this:

while read plugin;
do
    git add -A wp-content/plugins/$plugin &&
    git commit -m 'update $plugin plugin'
done; < plugins.txt

That slurps in that list of updated plugins and does a distinct git add and git commit for each.

When that’s done, remove plugins.txt.

All your plugins are quickly updated with WP-CLI, but you get nice granular Git commits and messages.


Do you need WordPress services?

Mark runs Covered Web Services which specializes in custom WordPress solutions with focuses on security, speed optimization, plugin development and customization, and complex migrations.

Please reach out to start a conversation!

Tips for configuring WordPress environments

Many WordPress hosts will give your site a “staging” environment. You can also use tools like Local by Flywheel, or MAMP Pro to run a local “dev” version of your site. These are great ways of testing code changes, playing with new plugins, or making theme tweaks, without risking breaking your live “production” site.

Here is my advice for working with different WordPress environments.

Handling Credentials

The live (“production”) version of your site should be opt-in. That is, your site’s Git repo should not store production credentials in wp-config.php. You don’t want something to happen like when this developer accidentally connected to the production database and destroyed all the company data on his first day.

Instead of keeping database credentials in wp-config.php, have wp-config.php look for a local-config.php file. Replace the section that defines the database credentials with something like this:

if ( file_exists( __DIR__ . '/local-config.php' ) ) {
    include( __DIR__ . '/local-config.php' );
} else {
    die( 'local-config.php not found' );
}

Make sure you add local-config.php to your .gitignore so that no one commits their local version to the repo.

On production, you’ll create a local-config.php with production credentials. On staging or development environments, you’ll create a local-config.php with the credentials for those environments.

Production is a Choice

Right after the section that calls out local-config.php, put something like this:

if ( ! defined( 'WP_ENVIRONMENT' ) ) {
    define( 'WP_ENVIRONMENT', 'development' );
}

The idea here is that there will always be a WP_ENVIRONMENT constant available to you that tells you what kind of environment your site is being run in. In production, you will put this in local-config.php along with the database credentials:

define( 'WP_ENVIRONMENT', 'production' );

Now, in your theme, or your custom plugins, or other code, you can do things like this:

if ( 'production' === WP_ENVIRONMENT ) {
    add_filter( 'option_gravityformsaddon_gravityformsstripe_settings', function( $stripe_settings ) {
        $stripe_settings['api_mode'] = 'live';
        return $stripe_settings;
    });
} else {
    add_filter( 'option_gravityformsaddon_gravityformsstripe_settings', function( $stripe_settings ) {
        $stripe_settings['api_mode'] = 'test';
        return $stripe_settings;
    });
}

This bit of code is for the Easy Digital Downloads Stripe gateway plugin. It makes sure that on the production environment, the payment gateway is always in live mode, and the anywhere else, it is always in test mode. This protects against two very bad situations: connecting to live services from a test environment (which could result in customers being charged for test transactions) and connecting to test services from a live environment (which could prevent customers from purchasing products on your site).

You can also use this pattern to do things like hide Google Analytics on your test sites, or make sure debug plugins are only active on development sites (more on that, in a future post!)

Don’t rely on complicated procedures (“step 34: make sure you go into the Stripe settings and switch the site to test mode on your local test site”) — make these things explicit in code. Make it impossible to screw it up, and working on your sites will become faster and less stressful.


Do you need WordPress services?

Mark runs Covered Web Services which specializes in custom WordPress solutions with focuses on security, speed optimization, plugin development and customization, and complex migrations.

Please reach out to start a conversation!