wp_localize_script(): What can you do with that third arg?

Let’s start with this, the param descriptions for wp_localize_script():

 * @param string $handle      Script handle the data will be attached to.
 * @param string $object_name Name for the JavaScript object. Passed directly, so it should be qualified JS variable.
 *                            Example: '/[a-zA-Z0-9_]+/'.
 * @param array $l10n         The data itself. The data can be either a single or multi-dimensional array.
 * @return bool True if the script was successfully localized, false otherwise.
 */
function wp_localize_script( $handle, $object_name, $l10n ) {

source

So you’re passing an array, right? Good.

If you’re not, tsk tsk. But let’s take a look at the good and the bad…

Array. Expected usage, you’re okay here:

wp_localize_script( 'jquery', 'exampleObject1', [
    'key' => 'value',
] );
// var exampleObject1 = {"key":"value"};

wp_localize_script( 'jquery', 'exampleObject2', [
    'value',
] );
// var exampleObject2 = ["value"];

String. Hit and miss:

wp_localize_script( 'jquery', 'exampleObject3', 'string' );
// var exampleObject3 = "string";

Above works by coincidence. This shouldn’t be relied upon.

wp_localize_script( 'jquery', 'exampleObject4', '' );
// var exampleObject4 = "";

Above throws a warning:

PHP Warning: Cannot assign an empty string to a string offset

Reduced example of the difference:

$l10n = 'string';
$l10n[0] = $l10n; // okay

$l10n = '';
$l10n[0] = $l10n; // warning. There's no character at the zeroth place to replace

Scalar. Miss (maybe hit because PHP is wacko):

wp_localize_script( 'jquery', 'exampleObject5', true );
// var exampleObject5 = true;

Above throws warning:

Cannot use a scalar value as an array

wp_localize_script( 'jquery', 'exampleObject6', false ); // no error
// var exampleObject6 = [""];

However, the above does not.

Reduced example, though it won’t really clarify things:

$true = true;
$false = false;

var_dump( is_scalar( $true ) ); // true
var_dump( is_scalar( $false ) ); // true

$true[] = 'adsf'; // Cannot use a scalar value as an array 
$false[] = 'jkl'; // okay why not

var_dump( $true ); // true
var_dump( $false ); // [ 0 => 'jkl' ] 

Why? No really, I’m asking.


So listen to the docs, and use an array.

WP-CLI: Require confirmation for search-replace

Worried about accidentally running a real search-replace command? Here’s how you can require confirmation for live-runs:

In your config file, add this:

require:
  - /path/to/search-replace-confirmation.php

In /path/to/search-replace-confirmation.php, add this:

<?php

$configurator = \WP_CLI::get_configurator();
$argv = array_slice( $GLOBALS['argv'], 1 );
list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args( $argv );

if ( 'help' === $args[0] ) {
    // no need to run any checks for help commands
    return;
}

if ( \WP_CLI\Utils\get_flag_value( $assoc_args, 'dry-run' ) ) {
    // no need to run any checks if we're already dry-running
    return;
}

if ( 'search-replace' === $args[0] ) {
        WP_CLI::confirm( 'Proceed with live run?' );
}

Don’t shortcut hook replication

A short post in the same vein as my last post, Don’t name form fields “update” or “link”.

We’ve probably all done something like this in one of our plugins:

$thing_title = apply_filters( 'the_title', $thing_title );

We want our thing’s title to get the same treatment as any other post title, so we use core’s filter. No big deal, right? Not so much.

In core, it’s actually used like this:

return apply_filters( 'the_title', $title, $id );

Importantly, it has an additional argument, $id, passed to it. source

Like with the accidental hook duplication in my last post, this means that callbacks expecting 2 arguments will end up throwing errors when the poorly-duplicated hook only provides one. Make sure when duplicating core hooks, all the expected arguments are passed.

Don’t name form fields “update” or “link”

In WordPress, every form field on the post edit screen results in a hook named pre_post_{$field} on save. Here’s how:

That means a field named “update” results in a variable filter hook named pre_post_update with 1 argument passed.

However, there’s a core action with that name already, and it passes 2 arguments: https://xref.trepmal.com/wp/wp-includes/post.php.source/#l3371

Similarly with link, there’s a core filter by that name already: https://xref.trepmal.com/wp/wp-includes/link-template.php.source/#l163

The problem?

If I have a form field named “update”, and I (or any plugin I’m running) hook into the core action like this:

add_action( 'pre_post_update', 'myplugin_pre_post_update', 10, 2 );
function myplugin_pre_post_update( $post_id, $data ) {
    // do stuff
}

Then the variable hook will call myplugin_pre_post_update but only pass the 1 argument. As of PHP 7.1, this will cause a fatal error

Besides, names as generic as ‘update’ and ‘link’ run the risk of conflict with another plugin.

Possible solution

If changing the field names isn’t feasible, you can adjust your callback:

add_action( 'pre_post_update', 'myplugin_pre_post_update', 10, 2 );
function myplugin_pre_post_update( $post_id, $data = null ) {
    if ( is_null( $data ) ) {
        // null $data means we're on the wrong hook instance, bail!
        return;
    }
    // do stuff
}

Work-Life Balance and Other Related Goals

1. Get out more.

I’m fortunate to work remotely. That is, I’m not bound to a physical office. Other people in this position use co-working spaces to make it easier to focus, or to have backdrops for video calls that don’t include pets or dirty laundry.
Unfortunately, there are no such options where I live. There are a few coffee shops with seating, but the atmosphere isn’t great. As a result, I spend all day every day at home.

Really.

My car is currently sitting in the garage, has about a quarter tank of fuel. I last filled it at the beginning of November (2017). I’m not confident that if I tried to go anywhere right now that my car would start. I’m not withing walking distance of anything (well, I’ve definitely taken walks into town, but it’s a couple hours), including the nearest bus stop. No Uber around here either. My circumstances are simply that I don’t need to leave much, when I do, I can often carpool.

I almost used my car yesterday, but I was blocked in by a guest so I borrowed someone else’s car for the errand. 🙂

The goal to get out more isn’t just about weekends. Though that’s certainly something I should do more. But even during the week, grab my laptop, drive to the waterfront, work a bit. Grab a coffee, top off the battery, drive to a viewpoint, work a bit. I’m really only limited by my cell reception (which admittedly, isn’t super great around here).

2. Ergonomics

This might seem a little ironic given the goal of getting out more, but I want my work space at home to be more comfortable. It’s not exactly uncomfortable, it was just never really intended to be used so much for so long. I wonder if my productivity would see an improvement if I had a space that seemed more intentional, if that makes sense.

I currently have a fixed standing desk, with a tall tractor-seat stool/chair because I get lazy. The desk is homemade (thanks Dad!), but never had any finish applied, so it’s showing its age more and more with every drop of coffee.

I’ve been eyeing the options out there, and I’m oddly excited for getting a monitor arm accessory. I have dreams of reducing the clutter on my desk, and it starts with not needing the monitor stand.

After the desk, I’ll look for a chair. Ideally I’d be able to try some out at local office supply stores, but their options may be limited, and there are some really neat ones online only. We’ll see.

3. Setting stricter “work hours”

Sometimes there is a need to work evenings and weekends. That’s okay, I often work better later in the day anyway. But does this stop me from being around during the mornings, or weekends when I’m not officially covering any shifts? Rarely.

I need to truly step away from work when it’s not work time. It probably starts with being more mindful of my Slack status. But it likely needs to graduate to things like quitting Slack over weekends, closing the work email tab, closing all my other work-related tabs, and starting fresh on Mondays, or whenever my week begins.

Since I don’t have kids or a spouse or any other similar requirements, I tend to let myself “be available” for off hours, but then I’m also available during regular hours because, well, they’re regular hours. So my mind spends a lot of time work-mode, even if I’m not actively on a task. I need to take real breaks and do so without feeling somehow guilty. Make no mistake, it’s purely an internal guilt, no one is putting this pressure on me. In fact, I wholly expect some coworkers to see this post and tell me to take a day off.


I shall stop at 3 goals for now, if only because I ended up with more words than I expected 😳

Ambiguous Relative Dates

Using relative dates like “next Thursday” can be confusing. (Is that this Thursday? Then why didn’t they say “this Thursday”?)

Try these polls for fun:

Does removing the weekend change things?

 

 

Cookie-Nonce authentication for REST API cURL Requests

The WordPress REST API is quite a feature, but it can be a struggle to deal with authentication. One option is Basic Auth. But can we leverage the built-in cookie authentication?

If you look at rest_cookie_check_errors(), you’ll see where it’s checking for an authentication cookie and valid nonce. Using WP-CLI, we can carefully piece together a cURL command that passes those values appropriately. Remember, cookies and nonces have a limited lifetime, so be sure to generate new commands as time goes by.

Example

Run wp-cli command

$ wp curl-rest --user=admin 

Output:

curl -H 'X-WP-NONCE: ooO0o00o00' --cookie \
  'wordpress_logged_in_wwWwwwWwwwWWwwwwwWwwwWWwwWWWwwwww=admin|xxxxxxxxxx|YYyyYyyyyYyYyYYYYYyyyYYyyyyYyyYYyyyyyyYYyyY|zZzzzzzZzZzzzzzZZzzzZzzzZzzZZzzzzzzZZzZzzzZZZzzZzZzzzZZzzzzzZzzz' \
  'http://local.wordpress.local/wp-json/wp/v2/settings'

Run curl command

$ curl -H 'X-WP-NONCE: ooO0o00o00' --cookie \
  'wordpress_logged_in_wwWwwwWwwwWWwwwwwWwwwWWwwWWWwwwww=admin|xxxxxxxxxx|YYyyYyyyyYyYyYYYYYyyyYYyyyyYyyYYyyyyyyYYyyY|zZzzzzzZzZzzzzzZZzzzZzzzZzzZZzzzzzzZZzZzzzZZZzzZzZzzzZZzzzzzZzzz' \
  'http://local.wordpress.local/wp-json/wp/v2/settings'

Output:
(prettified, I recommend the jq command line tool)

{
  "title": "wordpress.local",
  "description": "Just another WordPress site",
  "url": "http://local.wordpress.local",
  "email": "[email protected]",
  "timezone": "",
  "date_format": "F j, Y",
  "time_format": "g:i a",
  "start_of_week": 1,
  "language": "",
  "use_smilies": true,
  "default_category": 1,
  "default_post_format": "0",
  "posts_per_page": 10,
  "default_ping_status": "open",
  "default_comment_status": "open"
}

view raw

readme.md

hosted with ❤ by GitHub


<?php
if ( !defined( 'WP_CLI' ) ) return;
/**
*/
class trepmal_cURL_REST extends WP_CLI_Command {
/**
* Generate cURL command for REST API
*
* ## EXAMPLES
*
* # Generare command for fetching all administrators
* $ wp curl-rest –user=1 wp/v2/users?role=administrator
*
* @synopsis [<route>] –user=<user>
*
*/
function __invoke( $args, $assoc_args ) {
$args = wp_parse_args( [
0 => 'wp/v2/settings'
], $args );
list( $route ) = $args;
$route = trim( $route, '/');
if ( substr( $route, 0, 5 ) !== 'wp/v2' ) {
$route = "wp/v2/$route";
}
if ( ! $user_id = get_current_user_id() ) {
WP_CLI::error( 'Please pass –user' );
}
$expiration = time() + DAY_IN_SECONDS;
$manager = WP_Session_Tokens::get_instance( $user_id );
$token = $manager->create( $expiration );
$logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token );
$_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie; // for nonce creation
$url = rest_url( $route );
$nonce = wp_create_nonce( 'wp_rest' );
$cookie = LOGGED_IN_COOKIE . "={$logged_in_cookie}";
$nonce_header = "X-WP-NONCE: $nonce";
$curl = "curl -H '$nonce_header' –cookie '$cookie' '$url'";
$split_curl = _split_str_by_whitespace( $curl, 100 );
$curl = implode( "\\\n ", $split_curl );
WP_CLI::line( $curl );
}
}
WP_CLI::add_command( 'curl-rest', 'trepmal_cURL_REST' );

Things I’ve learned by working from home

I’ve been working from home full-time for most of the past 4.5 years. I haven’t reached any special milestone, but nevertheless I’m going to compile a list of some of the things I’ve learned, some bits of advice, and general observations. In no particular order, numbered for reference:

  1. Not commuting is awesome
  2. Sometimes your car battery will die if you don’t drive for a while
  3. I’m possibly too comfortable not leaving my house for days on end
  4. Getting a dog is probably healthy
  5. Playing fetch is a good way to get out of the house when you don’t really want to do anything
  6. I don’t worry about someone stealing my packages
  7. I’m pretty sure the UPS man thinks I’m unemployed, and possibly a recluse
  8. It’s easy to forget you’re still wearing pajamas at 2pm
  9. Comfy slippers are worth it
  10. Roosters are loud
  11. If you leave a window open, people on your video call are likely to hear some crowing, or even mooing
  12. Pets have no concept of work hours
  13. Pets have no concept of personal space
  14. A cat is likely to send at least one Slack message
  15. Check for nearby cats before entering any commands in a production terminal
  16. If you can’t be work productive, be personally productive
  17. A decluttered desk can mend a cluttered mind
  18. If you’re in the zone, don’t worry about the 4 coffee cups you’ve acquired next to your keyboard
  19. Someone in your life will believe you’re unemployed no matter how many times you tell them you work, just at home
  20. It’s easy to use “sorry I’m working” as an excuse to avoid social events, even on evenings and weekends
  21. Don’t do that. At least not too often
  22. It’s hard to take a sick day unless you’re at a high risk of literally vomiting on your keyboard
  23. Hardly anyone steals my lunch
  24. Sometimes I don’t eat lunch as much as snack between breakfast and dinner
  25. Taking an actual lunch break is hard
  26. Don’t forget to wash that hoodie
  27. Regular video meetings, even if sometimes unproductive work-wise, are good for recalibrating your teammates’ sarcasm levels
  28. Sarcasm is likely to backfire once in a while in text based communication
  29. Emoticons and emoji can actually be helpful in setting tone
  30. Imposter syndrome is very real
  31. People you look up to are also asking so-called stupid questions, they’re just in one of the other 2839416 Slack channels you haven’t stumbled into
  32. Don’t forget to stretch
  33. Sometimes the scenery gets boring
  34. Working from a coffee shop is tricky
  35. Working from the couch is cozy
  36. Mind your posture
  37. A second laptop charger is worth it
  38. No rules against sitting outside
  39. Working from a hammock is logistically challenging
  40. It’s hard to ignore work stuff during off-hours
  41. I’ve saved so much money by not commuting past fast food and coffee stands everyday. Oh, and the gas…
  42. Drink more water
  43. It’s hard to take “unnecessary” days off, but they are necessary
  44. I bet real office chairs are nicer than hard plastic, I should consider this
  45. The less you drive, the more handy a key hook is
  46. You’ll forget how tall/short your coworkers are
  47. Document everything
  48. I will never be able to convert UTC to PST in my head
  49. Yes, I know it’s just add 8 hours
  50. Video chat will never remember the proper audio/video settings

Command Line Shortcuts

Some command line shortcuts that might make your life easier. They’ve helped me, but sometimes I forget so I decided to group some of my favorites here.

To be specific, we’re talking bash. As a common default shell, there’s a good chance it’s what you’re using. So a lot of this can be found inside the bash manpage. If you’re using something else, I can’t say what of this might be compatible…

Event Designators

Ever need to repeat the last command? Easy, just use !!

$ echo some super-duper-annoy-to-retype command
some super-duper-annoy-to-retype command

$ !!
echo some super-duper-annoy-to-retype command
some super-duper-annoy-to-retype command

$ echo "!!" > what-was-that.txt
echo "echo some super-duper-annoy-to-retype command" > what-was-that.txt

$ cat what-was-that.txt
echo some super-duper-annoy-to-retype command

This is extremely handy if you meant to run the last command as sudo, just run sudo !!
Continue reading Command Line Shortcuts

Notes: Renaming and relocating directories in WordPress

This is not a guide (yet?). These are just notes for personal reference which may be expanded upon later.

Site owners/developers/administrators may find useful hints below, but please do not get mad at me if you break your site.


Methods were initially tested on a multisite-with-subdirectories installation, but are generally applicable to single and subdomain installations as well.

standard installation

familiar structure, e.g.

├── wp-config.php
└── wp-content/
    └── plugins/

nginx (subdirectory multisite)

if (!-e $request_filename) {
    rewrite ^(/[^/]+)?(/wp-.*)   $2                   last;
    rewrite ^(/[^/]+)?(/.*\.php) $2                   last;
}

Continue reading Notes: Renaming and relocating directories in WordPress