Categories
WordPress

Prettier multisite upload directories

One of my frustrations with WordPress multisite is how ugly the upload directories get. I know, most people don’t see these upload URLs… but I do see them and they bother me. In our domain mapping post we described one approach to handling this. In that case we used a PHP function to get WordPress to look at a different directory. But another approach is to allow WordPress to use the directories it knows, but rewrite the URLs with Nginx. We had to do this recently for an older multisite network still using ms-files.php internally.

In this case we have multisite set up as a network using subdirectories for the subsites. Since the subdirectories are already being used for regular content, we thought that using /subsite/files would make sense for the upload directories. So an image’s URL might be https://hostname.org/subsite/files/2021/05/image.jpg.

We put the nginx rewrite rule into our /server/tenseg.conf file:

rewrite ^/([_0-9a-zA-Z-]+/)?files/(.+)$ /wp-includes/ms-files.php?file=$2 last;

This transforms a URL like https://site.org/subsite/files/image.jpg into https://site.org/wp-includes/ms-files.php?file=image.jpg.

Really, we might want to consider dumping ms-files altogether.

Categories
SpinupWP WordPress

Bad Link

One of our clients accidentally used a preview link when publicizing a post in a mass email. Of course, the readers of this email could not resolve a link to a preview of a post on the client’s WordPress site. Since this link went out by email, there was no opportunity to correct the mistake on that end. We wanted to create a redirect from the preview link to the actual page using Nginx.

We created a file called custom-redirects.conf in their site’s server directory. In this case that was at /etc/nginx/sites-available/ediblecleveland.com/server/custom-redirects.conf. In that file we added:

if ( $query_string = "preview_id=15781&preview_nonce=4538cdad70&_thumbnail_id=15792&preview=true" ) {
	return 301 /archives/15781;
}

This simply looks for the very specific query string that was accidentally used in the email and, if found, returns the plain post instead.

After making this change we used sudo nginx -s reload to reload the configuration with syntax checking, so we didn’t accidentally bring Nginx down with a syntax error.

Categories
SpinupWP WordPress

Domain mapping with a WordPress network

A few years ago when I wanted to use domain mapping for domains in a WordPress network, it was a bit of a chore. At that time I had to use a special domain mapping plugin and another tool called “sunrise.” This week, when setting up domain mapping with a network generated by SpinupWP we discovered things had gotten a lot simpler.

Since WordPress 4.5 domain mapping has become a native feature. All we had to do was use SpinupWP to define additional domains for our network site, create a subsite for that domain on WordPress, and then go to Sites and edit that site to put the domain name into the Site Address (URL).

That worked! But then we decided we also wanted upload URLs that were a bit more friendly than the site numbers that WordPress automatically uses. A typical piece of media on a site mapped subsite would get a URL like https://subsite.com/wp-content/uploads/site/3/2020/2/media.jpg. That works, but I find the site/3 a bit too mysterious and revealing at the same time. It is mysterious in that it really means nothing to a person reading the URL. It is revealing in that it is trivial to guess that there might be a site/4 or a site/5.

We wondered if we could not use something like sub instead, so that the URL would become https://subsite.com/wp-content/uploads/sub/2020/2/media.jpg. This would take two things, (1) a way to define the string to use for a given subsite, and (2) a way to tell WordPress to use that string instead of the blog ID number in the upload URLs.

We decided to keep defining the string as an experts-only affair. Basically, if this string was present then we wanted to assume an expert had decided the substitution should take place. Since only experts were going to do this, we left it to a WPCLI command:

$ wp --url=https://subsite.com option add tg_upload_dir sub

In other words, we created an option to hold the string. If that option exists, we would make the substitution.

To carry out the substitution we create a one-function upload directory modifier plugin to look for that option and use if when found. The heart of this plugin is the following function:

add_filter( 'upload_dir', 'tg_upload_dir_filter' );

function tg_upload_dir_filter( $dirs ) {
	global $wpdb;
	
	$directory = get_option('tg_upload_dir');
	
	if (! $directory) {
		return $dirs;
	}
		
	$dirs['baseurl'] = site_url() . '/wp-content/uploads/' . $directory;
	$dirs['basedir'] = ABSPATH . 'wp-content/uploads/' . $directory;	
	$dirs['path'] = $dirs['basedir'] . $dirs['subdir'];
	$dirs['url']  = $dirs['baseurl'] . $dirs['subdir'];
	
	return $dirs;
}

While this gave us the URLs we wanted, we still had to take one more step to get these URLs to work: we had to create a symlink from the directory WordPress had created to the friendlier name we wanted to use. To accomplish this we used SSH to connect to the server behind our SpinupWP site and then did the following:

$ cd files/wp-content/uploads
$ ln -s sites/3 sub

The beauty of this approach is that both the sites/3 URL and the sub URL will work, so we don’t have to search and replace existing media URLs unless we want to.