After running sudo dnf update && sudo dnf upgrade today Chrome wasn’t working as expected. Icons weren’t showing on the default Chrome landing page and text wasn’t showing in Google Docs, among other issues with web content not being displayed.

One quick command clears some residual cache and gets it working again.

rm -rf ~/.config/google-chrome/Default/GPUCache/

Thanks reddit.

One of the biggest tips I’d give to any new programmers is that your code should gracefully degrade. Let’s look at a simplified example in a recent WordPress project I was working on.

In a plugin there was a line similar to what you’d see below that includes a file from a theme.

require_once plugin_dir_path(__FILE__) . '../../themes/<theme-name>/lib/assets.php';

In our default install this isn’t a problem because the theme exists and assets.php also exists. So the file is included and we have no issues.

But this week I’ve been building a system to check which theme is active and force activate a specific theme for a site if it’s not active. It also lets us know if the theme isn’t present so it can’t be activated. While testing this I renamed the theme folder to have it deactivate itself and then the line above breaks.

This is where we should fail gracefully and check if we have the file in the expected location before we try and include it. Further, outside of standard PHP notices, there is no reporting at any level about the issue.

I’ve added a task to fix this, but this is what the fix would look like in pseudo-code if you’re curious.

  • Check if the theme exists with wp_get_themes()[^1]
  • If theme exists, check if the file in question exists
  • If either of the above fail, let someone know about it in your reporting system so that the issue can be resolved.

In the case above, I’d send a message to the our dev slack channel along with some information about what the fix should be and if a developer should be involved. We have a number of errors that can be handled by support staff without involving a developer because of the tooling we’ve already built.

In general, before you try to use some custom functionality, make sure it exists and then deal with the case if it doesn’t exist so your whole site doesn’t die.

Yes we should not even have a plugin/theme dependency like this. That is a different topic to address and one of the many items of technical debt we need to dig out of.

[^1]: This can be an expensive function so be clear about it’s cost and that the cost of the function increases as you add more themes.

Right now I’m working on a Google Analytics 4 integration that needs some data and views. To get the clicks/views I’m using the Selenium IDE Firefox Extension which records my clicks and the replays them. But to even have content for those clicks, I need to generate a bunch of it.

Enter WP CLI Random Content by Bryan Richards.

I’ve used two commands so far. wp random generate --count=50 to generate 50 posts. Then wp random generate --count=50 --post_type=question to generate 50 questions for the WP FAQ Manager plugin.

WP CLI Random Content has far more options than I’ve described above. You can have it add taxonomies to your generated content, use --with-terms=true to have it generate terms first then generate content and attach it to those terms.

Overall, it’s a one stop shop for generating basic content for testing your WordPress sites.

Google Analytics 4 API requires the bcmath PHP extension to be installed but not every server will have it. To find out if you do type the following line in terminal.

php -r "print_r(get_loaded_extensions());"

The output will be something like you see below. On this instance you can see that I have bcmath installed already.

If you don’t have bcmath installed already then you’ll need to run the following command, assuming you have PHP 8.0 installed and that your server is uses apt to install its packages.

apt-get install php8.0@bcmath

Once that’s installed you’re ready to use Google Analytics 4 API to build your own analytics dashboard.

We recently received an email from Cloudflare about their Page Shield service and I was asked if we needed to implement it and what it did. So let’s take a look.

What is Cloudflare Page Shield?

Cloudflare Page Shield is a service that protects against Magecart attacks on your e-commerce site. So if you’re not collecting Credit Cards or running any type of payment gateway, even linking to PayPal, then you don’t need Page Shield. For those running an eCommerce site, read on.

Magecart attacks are named after the Magecart hacker group that cropped up in 2015. They got access to third-party dependencies and used them to inject their own JavaScript to capture the Credit Card information as it passed through the victim’s sites.

So this means that some code your eCommerce system relied on was infected. Then it was included in the eCommerce system without the authors knowing it was infected and credit card details were stolen.

Cloudflare Page Shield is aimed at stopping this by monitoring what scripts are running on your site and alerting you to changes in them so that you can proactively investigate if the changes are intended.

The Good and Bad on Page Shield?

It’s great that Page Shield is going to monitor your scripts and let you know what changes so you can make sure that the changes are desired. For the group of sites I run, we’d see a change every few days to our scripts as we roll out new features and keep the site dependencies up to date.

This means a lot of overhead and noise we’ll have to filter through. I’d much prefer it if they were inspecting specifically for malicious scripts and letting us know about that.

Second, at this point, you have to go check a dashboard to see what changed. For most teams, this will happen at first, and then you’ll check it once a week. Then you’ll check it once a month…then you’ll randomly stumble across it once in a while and look at all the changes and not bother checking anything.

Again, I’d prefer that Cloudflare was proactively looking for malicious scripts and then giving me options for how I want to be alerted. My team would prefer to see them in a Slack channel, but others would want them in email.

I love that Cloudflare is taking another step in keeping our sites secure, I just wish it was a bit more useful and didn’t have a chance of overwhelming my team (of one), managing 80 sites, with spurious notifications.

PHP 7.4 went end of life at the end of November 2022 so I’ve been digging into what PHP 8 brings us, besides noticable performance improvements.

Here are the things I’m looking forward to right now.

Match Expression

Switch statements are powerful, and can be quite unwieldy if they get long enough. PHP 8 now brings us Match Expression to help clean up Switch.

In PHP 7 a switch statement that needed to return different text depending on input would look something like this.

switch( $input_text ){
	case 'one':
		$output_text = 'one';
	case 'two':
		$output_text = 'two';
	case 'three':
		$output_text = 'three';

PHP 8 allows us to simplify that to:

$output_text = match( $input_text ){
	'one' => 'one',
	'two' => 'two',
	'three' => 'three',

Far less typing and easier to read.

Better String Handling

There are three excellent new string functions to be used.

str_contains( $haystack, $needle ) returns true if the string ($needle) is contained inside the $haystack. The following will all evaluate to true.

// true because `thing` is somewhere in the string
str_contains( 'thing-one and thing-two', 'thing' );
str_contains( 'one-thing and another', 'thing' );

There are also two functions that allow you to evaluate if your string starts or ends with the search parameter.

// this is true
str_starts_with( 'thing-one thing-two', 'thing' );
// this is false
str_starts_with( 'one-thing and another', 'thing' );

// this is true
str_ends_with( 'thing-one thing-two', 'two' );
// this is false
str_ends_with( 'two-thing and another', 'two' );

Nullsafe Operator

We’ve all been in the spot where we have a nested object and we need to check at mutiple levels to see if we have a null value before we finally access the final item we want.

In PHP 7 our code would look something like this:

if ( $user->address ){
	echo $user->address->street;

Now with the nullsafe operator we could write the entire statement in one line.

echo $user?->address?->street;

If we have a null value at any level in that chain it will return null.

PHP 8 Speed Improvements

While PHP 8 doesn’t bring a massive speed boost like PHP 7 did, we still see some notable improvements. Kinsta showed that, compared to PHP 7.2, PHP 8.0 can handle 50% more requests.

I’ve upgraded 80+ sites I run and we’ve had a number of customers reach out asking what we did to speed the sites up. They had no idea anything was coming so this unprompted feedback from non-technical users shows that people notice when your site gets faster.

Can we use PHP 8 in WordPress?

Yeah the answer to this question for WordPress developers is, no you can’t start using PHP 8 right now for public projects like plugins/themes. According to statistics 56.4% of WordPress sites are still using PHP 7.4. If we broaden out our stats to look at any site running PHP 7, we have about 73% of active WordPress installs using PHP 7.

For my regular coding work, I could start using these PHP 8 features but only for plugins that I know are going to be on our install only. I actually can’t even do that until I resolve one or two legacy issues that have 4 of our sites running PHP 7.4 still.

We’ve only got a year until PHP 8.0 heads to end of life though, so maybe next year I can start using everything in PHP 8 without worrying about publicly released code.

I took a detour for a good chunk of the year to VSCode, but as always I missed the keyboard focus of Vim so I’m back there.

One thing I did regularly in VSCode was to limit a search for a string to a specific filetype. I didn’t know how to do that in Vim until today.

ACK $term --type=php will limit your search term to files with the .php extension.

You can find my WordPress specific vim configuration here on Github. I need to dig back into it and update it because I’m a Vim user.

You can find the full documentation on ACK here.

Recently this audit summary from US local governments and courts came up in the security channel for a client. Specifically item 2.1 which recommends that users are routinely asked to change their passwords. Specifically it says:

Without requiring passwords to be periodically changed, the likelihood that accounts could be compromised and used by unauthorized individuals to gain access to sensitive information is increased.

Ensure passwords are periodically changed to prevent unauthorized access to computers and data

On the face of it, this sounds like a good idea. If there is a password breach, then making sure that you’re users are regularly rotating their passwords should help ensure that any compromised passwords are periodically changed. No more worries about those compromised passwords…right?

What Forcing Password Changes Really Does

By nature, humans are lazy. That’s why we reuse passwords and why password is consistently a common password found in breaches. When you force password changes on users regularly, they just get lazier. password becomes password1 then becomes password123, both of which are on the list above of regularly compromised passwords.

That brings us to this 2010 study that examines the utility of getting people to change their passwords. It finds…that users just transform their passwords in predictable ways I highlighted above. The study shows that around 41% of passwords that were regularly changed would be crackable with the techniques shown in their study. It shows that 17% of passwords would be crackable in 5 guesses.

So forcing password recycling seems like a good idea, but does little to improve security.

What Should You Do Instead?

Let’s talk about some of the things you should be doing with your passwords to keep them strong and secure according to NIST Guidelines.

First, and this isn’t specifically in the guidelines, you should be using a password manager like 1Password or Bitwarden. One of the biggest reasons users choose insecure passwords is that they try to remember them. Human memory isn’t great for random strings of text, so they use insecure password practices like including their username or the site name in their password. By having a password manager generate your passwords for you, you can be more sure that you’re getting truly random unique passwords.

Second, when you’re accepting user passwords check them against data breach databases and reject passwords that match these databases. Password databases from breaches are used regularly in attacks that try to guess passwords so just don’t allow them.

Third, use two-factor (2FA) authentication, but don’t allow SMS as a way to send SMS codes. It’s not hard to spoof SIM cards, or to use social engineering to get access to an account you shouldn’t have access to. If you’re able to do this then you have access to SMS 2FA codes. You should be using a tool like Authy to store your 2FA codes.

Fourth, lock users out of accounts and require admin intervention after 10 password attempts. I suppose it would be okay to lock someone out for a limited amount of time on the first 10 guesses, but then if you allow them to try again after 20 minutes those next 10 guesses should lock them out entirely until an admin deals with whatever is going on. The higher the risks to a breach, the more strict you should be.

Fifth, don’t allow password hints they make passwords trivial to guess. So much data is out there that someone could find out that the name of my first dog was…nope not going to tell you. Still, I’m sure I’ve said it on social media before. A good rule of thumb is that if your password has a hint that would let you guess it, it’s a bad password.

Finally, context specific items such as the username or site for the account should not be allowed as part of the password.

For IT managers, get people using a password manager and do whatever you can to ensure that people use it. Forcing them to change their passwords periodically is so much less secure than using 2FA and using proper passwords. Just stop the practice.

We recently started to update an old gulp based build process at work by using Laravel Mix. Mix is a wrapper around webpack which helps take a bunch of the setup headache away. If you have a very complex build, then Mix may not be for you, but for 90% of the needs of developers mix is going to serve you well.

I was able to get everything compiling easily, and then realized that I wasn’t being provided with sourcemaps for my css files. This means that I won’t be able to use a browser’s developer tools to see the source .scss file for a given css rule.

According to the mix documentation I should be able to take the code below and add a .sourceMaps(); parameter to it if I want sourcemaps to be generated.

mix.scss( 'source-file', 'destination-path');

This code should generate sourcemaps.

mix.scss( 'source-file', 'destination-path').sourceMaps();

Unfortunately, it doesn’t work. I was still left with my rendered css without sourcemap files generated alongside them. There is even an issue from 2017 highlighting the problem

Like many things as a developer, the solution was found by reading through a bunch of comments on the issue and forum posts. In the end the code below rendered my files as expected.

mix.webpackConfig({ devtool: "source-map" });
mix.scss( 'source-file', 'destination-path').sourceMaps();

You need to both configure webpack to generate sourcemap files and tell mix to generate sourcemap files.

Yup this is contrary to the documentation, which makes no mention of the webpack configuration needed. One of my biggest frustrations as a developer is the lack of care put into documentation. Though the upside is that I can write about it and that generates business for me as people find solutions I write about and then hire me because they figure I can solve other problems they have.

You want to maximize your sales, and streamlining your checkout is a crucial step to this.

In 2015 Barilliance found that the global average cart abandonment rate was over 70%. Take a look at your sales, and realize that there was another 70% of people that had a product in their cart, only to leave. Maybe they even purchased from a competitor?

With the right changes in your checkout process, you could cut your cart abandonment rate by up to 50%. That’s a significant impact on your bottom line. What could you do with the revenue that a 50% higher conversion rate would bring?

Read the whole thing on Liquid Web