1072WordPress Multisite and Switching Subdirectories

Notes for changing Wordpress Multisite Subdirectories:

Step 1

Update siteurl & home in wp_X_options Don’t forget the trailing slash

Step 2

Change corresponding paths in wp_blogs

Step 3 (Optional)

Clear Caches

Step 4

Check Image upload folders

Step 5

define( 'SITE_ID_CURRENT_SITE', 1 );
define( 'BLOG_ID_CURRENT_SITE', 1 );

1065Not-so-advanced Custom Fields

The traditional Custom Fields in Wordpress have been around since the beginning, gives some degree of customability to the posts. They are very basic, but the work.

Soon after, the Advanced Custom Fields become the norm, adding a nice UI on top of the custom fields, and enabling things like checkboxes, time/date, repeater, etc.

All was great in Wordpressland, but the ACF were sold to WP Enginge who are now trying hard to monetize the ACFs. Instead of payment per installation, they now moved ACFs to a monthly/yearly subscription model.

I still keep using ACFs for client work, but try to remove it from my personal sites - like this one. All it did was to have a checkbox to enable/disable Markdown on the posts.

Markdown is now by default on, ACF no longer needed.

Also, I was stuggling to show the original Custom Fields:

Only AFTER I uninstalled ACF, the option showed up again!

1060Getting multiple ACFs via raw MySQL in ClassicPress

ACFs are a great (legacy?) way of storing additional data in a ClassicPress/Wordpress installtion. But things can get a but ugly when you have thousands of posts, each with ACFs maybe nested Repeater ACFs. Getting data out of larger installation with get_posts and WP_Query can quickly hit the limits of the DB installation and fail.

The solution? A raw, hand-crafted MySQL query:

Getting a Single Custom Field

SELECT wp_postmeta.meta_value             // return the meta_value
  FROM wp_posts, wp_postmeta
  WHERE wp_posts.post_status = 'publish'    // publish posts only
   AND wp_posts.ID = wp_postmeta.post_id
   AND wp_postmeta.meta_key = 'my_key'       // get value from 'my_key'

Getting the results with $wpdb->get_results().

$results = $wpdb->get_results($query);

Example Output

Array
(
    [0] => stdClass Object
        (
            [meta_value ] => 123
        )
    [1] => stdClass Object
        (
            [meta_value ] => 456
        )
)

That works great, if you want to get one Custom Field, but how about multiple Custom Fields?

Getting Multiple Custom Fields

Custom fields are stored in the wp_postmeta table and defined by the meta_key and meta_value column.

SELECT p.ID, m1.meta_value as v1, m2.meta_value as v2 
FROM wp_posts p
LEFT JOIN wp_postmeta m1 ON p.ID = m1.post_id
LEFT JOIN wp_postmeta m2 ON p.ID = m2.post_id
WHERE p.post_status='publish'
AND m1.meta_key = 'my_key'
AND m2.meta_key = 'my_other_key'

Is it important to note - and slightly unintuitive - that the select line also declares aliases which will be used in the rest of the query:

  1. The p in p.ID is a shortcut for wp_posts
  2. The m1 in m1.meta_value is a shortcut for wp_postmeta
  3. Same as m2, but we want to select and JOIN different meta key we also need to have two shortcuts for wp_postmeta.
  4. meta_value as v1 is also important. If we would not use ... as v1 then the return array would include meta_value as a key and m2 would overwrite m1. Does not have to be v1 and v2, use whatever you like.

Example Output

Array
(
    [0] => stdClass Object
        (
            [ID] => 123
            [v1] => 33
            [v2] => 20130402
        )
    [1] => stdClass Object
        (
            [ID] => 456
            [v1] => 22
            [v2] => 20130404
        )
)

Getting Multiple Custom Fields including ACF Repeater

The ACF Repeater fields also stores its values in wp_postmeta, following this schema: repeatername_nr_fieldname. Let's say we have a repeater field called videos and a sub-field called video, the meta_keys in wp_postmeta would look like this:

videos_0_video
videos_1_video
videos_2_video
videos_3_video
...

That means we need to modify the previous query, because the we can't be sure how many meta_key we have.

SELECT p.ID, m1.meta_value as v1, m2.meta_value as v2 
FROM wp_posts p
LEFT JOIN wp_postmeta m1 ON p.ID = m1.post_id
LEFT JOIN wp_postmeta m2 ON p.ID = m2.post_id
WHERE p.post_status='publish'
AND m1.meta_key REGEXP '[[:<:]]videos_[0-9]*_video[[:>:]]' 
AND m1.meta_value > 0
AND m2.meta_key = 'my_key'

AND m1.meta_key REGEXP '[[:<:]]videos_[0-9]*_video[[:>:]]' is a regular expression with some MySQL-specific syntax: [[:<:]] means beginning of string and [[:>:]] stands for end of string.

Sources

1007Regenerating Thumbnails in WordPress

Option 1: Plugin

The Regenerate Thumbnails Plug-in.

This option is usualy slower - and some hosting providers might confuse it for a malicious attach and block the IP.

Option 2: WP-CLI

WP-CLI is the command line interface for WordPress/ClassicPress.

Installation

From the WP-CLI Guide

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar

Run --info from your WP root directory, to check if it works:

php wp-cli.phar --info

If you get a json_encode error, it means your PHP version is not compatible with WP-CLI.

PHP 7 was the default on one server, it did not work.

Check for other PHP versions
which php
// /usr/bin/php

ls /usr/bin/php* 
// php80 php81 php82 php83

Let's use the latest verson of PHP.

php83 wp-cli.phar --info

Regenerating

Regenerate all images, without confirmation.

php83 wp-cli.phar media regenerate --yes

Regenerate thumbnails only.

$ php83 wp-cli.phar media regenerate --image_size=thumbnail

More options for regenerating images with WP-CLI:

# Regenerate thumbnails for given attachment IDs.
php83 wp-cli.phar media regenerate 123 124 125

# Re-generate all thumbnails that have IDs between 100 and 200.
seq 100 200 | xargs php83 wp-cli.phar media regenerate

# Re-generate all thumbnails that have IDs between 100 and 200.
seq 100 200 | xargs php83 wp-cli.phar media regenerate

# Re-generate all thumbnails that have IDs between 100 and 200, only thumbnails
seq 100 200 | xargs php83 wp-cli.phar media regenerate --image_size=thumbnail

#### Error

`Error: Error establishing a database connection.`

When working on _localhost_, use `127.0.0.1` instead of `localhost` in wp.config
```php
define( 'DB_HOST', '127.0.0.1' );

985Customising Pagination in WordPress

Getting and Customising Pagination:

function getPagination() {
  global $wp_query;
  $a = paginate_links(array(
    'current' => max(1, get_query_var('paged')),
    'total' => $wp_query->max_num_pages,
    'type' => 'array',
    'aria_current' => false,
    'show_all' => true,
    'end_size' => 2,
    'mid_size' => 2,
    'prev_next' => true,
    'prev_text' => '<div class="pg_arrow left"></div>',
    'next_text' => '<div class="pg_arrow right"></div>',
  ));
  if (empty($a)) return false;
  foreach($a as &$l) {
    $l = str_replace('prev page-numbers', 'pg_item', $l);
    $l = str_replace('next page-numbers', 'pg_item', $l);
    $l = str_replace('page-numbers', 'pg_item pg_num', $l);
    $l = str_replace(' aria-current=""', '', $l);
    $l = str_replace('span', 'a', $l);
    $l = str_replace('current', 'active', $l);
  }
  return $a;
}

Calling:

if spaces are needed in front

foreach(getPagination() as $p) {
  echo "   " . $p . "\n";
}

no spaces

echo implode("\n", getPagination());

984WordPress – Getting $post from blog home

Problem:

ACFs in sidebar-top.php in home.php are not displaying. $post is set to the first Post, rather than the home.php page.

Solution:

Check is is_home(), assign $post to get_option('page_for_posts').

if (is_home()) {
  $post = get_option('page_for_posts');
}

953Changing Languages in WordPress

Install additional language:

Change user language:

921Forcing a Database Upgrade in ACF/WordPress

Background:

A site that was developed some years ago with Wordpress 4.x and ACF 4.x got moved to a new server. During the migration process, Wordpress and the Plug-ins were updated to their latest version - I assume, before the MySQL DB got migrated, which let to the following complaint:

"ACF are not showing in ACF 5.x"

After some detective work, I realise that the data was still present. ACF v4.x was storing the ACF data in wp_options, ACF v5.x is storing it in wp_termmeta.

Which is great, because all that is needed, is to update the DB! But how to do it?

First attempt: Re-install ACF 4.4.12, then update to ACF 5.x

Didn't work as expected.

Second attempt: change the acf_version in wp_options

In the wp_options, the acf_version is set to the current WP version, 5.7.6 in this case. Setting it to 4.4.12, triggered the ACF DB update script, the ACF data got migrated to wp_termmeta, the site is working again as expected.

Shout out to the ACF Support Pages for solving the last piece of the puzzle.

914Show WordPress Theme Menu

$l = get_nav_menu_locations(); $m = wp_get_nav_menu_items($l['footer-menu']); foreach($m as $i) { // $i->url; // $i->title; }

913WordPress functions.php

// update_option('siteurl','http://127.0.0.1/my-site'); // update_option('home','http://127.0.0.1/my-site');

// add excerpts to pages add_post_type_support('page', 'excerpt');

// remove auto-p in blog content remove_filter('the_content', 'wpautop');

// replace \n with <br /> // substitute
for line breaks in the content function addLineBreaks($content) { return str_replace("\n", "\n<br />", $content); } add_filter('the_content', 'addLineBreaks');

// register menu function register_theme_menu() { register_nav_menu('footer-menu', 'Footer Menu'); } add_action('init', 'register_theme_menu');

Show Wordpress Theme Menu