Skip to main content

How to Automatically Remove ‘Uncategorized’ from Multi-Categorized Posts in WordPress

This script is designed to efficiently manage and clean up the categorization of posts in a WordPress site. Specifically, it targets posts that are currently assigned to the ‘Uncategorized’ category. The script automatically scans through all such posts and checks if they are also assigned to any other categories.

If a post is found to be in ‘Uncategorized’ as well as in one or more additional categories, the script will remove it from ‘Uncategorized’. This process helps in maintaining a more organized and meaningful categorization of content, ensuring that posts are not left in the default ‘Uncategorized’ category if they have been appropriately categorized elsewhere. This is particularly useful for large WordPress sites, where posts might inadvertently be left in ‘Uncategorized’ during the content creation process.

By running this script, site administrators can ensure a cleaner, more accurate categorization of their posts, enhancing both site navigation and SEO performance.

function remove_uncategorized_from_all_posts() {
    $uncategorized_id = get_cat_ID('uncategorized');

    // Get all posts that are in 'uncategorized' category
    $args = array(
        'category__in'   => array($uncategorized_id),
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
    );

    $posts = get_posts($args);

    foreach ($posts as $post) {
        $categories = wp_get_post_categories($post->ID);

        // If the post has more than one category, remove 'uncategorized'
        if (count($categories) > 1) {
            $categories = array_diff($categories, array($uncategorized_id));
            wp_set_post_categories($post->ID, $categories);
        }
    }
}

// Run the function - you can comment this out after it's run once
// remove_uncategorized_from_all_posts();

How to Use

  1. Backup Your Database: Before running this script, make sure to back up your WordPress database. This script will modify your posts, so it’s important to have a backup in case something goes wrong.
  2. Add the Script: Place the function in your theme’s functions.php file.
  3. Run the Script: Uncomment the call to remove_uncategorized_from_all_posts() and save the file. This will execute the function.
  4. Comment Out or Remove the Script: After the script has run, you should comment out or remove the call to the function to prevent it from running on every page load. This is important because the script is resource-intensive and should only be run once.

Important Notes

  • This script is designed to run once. Running this on every page load would significantly impact your site’s performance.
  • The script uses get_posts with 'posts_per_page' => -1, which means it will attempt to load all matching posts at once. If your site has a very large number of posts, this could lead to memory issues. In such cases, consider processing the posts in batches.
  • Always test scripts like this in a staging environment before running them on a live site to avoid unintended consequences.
  • If you’re not comfortable editing your theme’s files or running this kind of script, you might want to seek assistance from a developer.

Getting Spatie Media Library’s PDF thumbnail to work with Laravel

I’ve just spent a good couple of hours troubleshooting why Spatie Media Library won’t create a thumbnail of a PDF I upload to my server.

I’ve already setup up the correct code to generate a conversion, but nothing happens.

The real issue is that there are a couple of dependencies to make it work, which is Ghost Script and Imagick. Both of these need to be installed on your server for it to work.

Install Ghost Script
sudo apt-get install ghostscript
Once installed, check it works: gs –version

Install PHP Imagick
sudo apt-get install php-imagick
Once installed, check it works: php -m | grep imagick

However, even when everything is set up properly, I was receiving a server error:
“not authorized @ error/constitute.c/ReadImage/412”

To fix this, you need to SSH in and edit the policy.xml of Imagick located into etc/ImageMagick-6/policy.xml

Look for this line:

 <policy domain="coder" rights="none" pattern="PDF" /> 

and replace with:

 <policy domain="coder" rights="read|write" pattern="PDF" /> 

You also may want to add:

 <policy domain="coder" rights="read|write" pattern="LABEL" /> 

You then need to restart your server, in my caseĀ sudo service nginx restart

Then, restart your PHP FPM Workers.

Only then, should your PDF thumbnails work.

Unfortunately, I couldn’t get it working on Laragon locally.

Encrypt and Decrypt password using PHP

In PHP, you can use AES password encryption if you want to be able to store passwords securely and decrypt them when needed.
Be sure to put your secret key in an ENV file – if a hacker gets your secret key, they can decrypt the password.

You can use a random long string as the secret key for AES encryption in PHP. The key should be a random string of characters that is at least as long as the block size of the AES algorithm you are using. For AES-128, the key length should be 128 bits (16 bytes), for AES-192, the key length should be 192 bits (24 bytes), and for AES-256, the key length should be 256 bits (32 bytes). It’s important to note that the key must be kept secret and should be generated randomly and securely.

In PHP, you can use the built-in openssl_random_pseudo_bytes() function to generate a random key of the appropriate length.
It’s also important to use a good library that implements AES encryption properly, like OpenSSL or sodium (extension for PHP 7.2+), and make sure to use a proper mode of operation for AES.

It’s also worth noting that, for better security, it’s a good practice to use a key derivation function (KDF) to derive a key from the password. It’s also important to update the key regularly, for example by using a key rotation scheme.

 $secret_key = 'xj1X7O0FaAYDsNB4bU60YjdlrpIGMp9mkIMmGZoQGaQrDyPfmCqAWEU2u1nciHhWyvDVd276HAwywuIWlma3hd24fWNq8RG6kwahqt5iMZMlZFOdqSnVjq9NKeebzBPKJO6CN04z8Gi4j9wVmrp5tmO9KRKmryCQIykeb5NwcrCsZOvhQTAwO4oXevwtHQdEfrM5YI2XUohIfSSKozFcVIwms9HRuN1Fwyj9pP1voPW9zjb3kTF7ayxhSahLhoHv';

    // The data to be encrypted
    $plaintext = "MySecretPassword";
    
    // Encryption
    $cipher = "AES-128-CBC";
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $secret_key, OPENSSL_RAW_DATA, $iv);
    $ciphertext = base64_encode($iv . $ciphertext_raw);
    
    // Decryption
    $ciphertext_dec = base64_decode($ciphertext);
    $iv_dec = substr($ciphertext_dec, 0, $ivlen);
    $ciphertext_raw_dec = substr($ciphertext_dec, $ivlen);
    $plaintext_dec = openssl_decrypt($ciphertext_raw_dec, $cipher, $secret_key, OPENSSL_RAW_DATA, $iv_dec);
    
    echo "Encrypted: " . $ciphertext . "\n";
    echo "Decrypted: " . $plaintext_dec . "\n";

Laravel session value not persisting when using AJAX requests

I had a very weird issue in Laravel where a specific session value was not persisting after an AJAX request.

To give it some context, I did two AJAX requests, one after the other.

The first AJAX request sets the session value.

The second AJAX request was then not seeing that value.

The issue is a known limitation with sessions in Laravel and the way to fix this is to enable SESSION_BLOCK.

Go into your session.php and if it doesn’t exist, add this:

'block' => env('SESSION_BLOCK', false),

Then, add SESSION_BLOCK=true to your ENV file.

Disk space almost full on cPanel server

I had an issue where my cPanel server was quickly running out of space. All user accounts combined were a fraction of the disk space, so I had to look in the server to see what was causing the disk usage to increase rapidly each day.

To find the issue, SSH’d into the server and ran this:

Find largest files
du -hs * | sort -rh | head -5

Once the files are found, remove them:
rm <filename>

or clear them, instead of deleting:
cat /dev/null > {FILENAME}

The culprit for me was “messages-” log files in /var/log.

Attach unique in BelongsToMany Laravel/Eloquent

As you probably know, you can use the attach() method to relate two models within a BelongsToMany relationship. The only problem with attach() is that it doesn’t check to see if the relationship already exists. So, essentially, you could attach the same model more than once to a relationship, which isn’t ideal.

For instance, you have pizzas and ingredients.

You could always do something like this:

$relationship = $pizza->ingredients()->where('ingredient_id', $ingredient->id)->get();
if(!$relationship)
{
$pizza->ingredients()->attach($ingredient);
}

Or, you could use this method, which checks if the relationship exists and it doesn’t double up:

$pizza->ingredients()->syncWithoutDetaching($ingredient);

What this will do is sync the ingredient with the pizza (like the sync() method), however, if the relationship already exists, it won’t do anything. The relationship will stay, and nothing else will detach.