Redirecting WordPress 404 errors

Interestingly, there turns out to be a built-in mechanism for attempting a redirect on 404 errors in WordPress. It is amazing but this function is built in and it is called redirect_guess_404_permalink(). It is even more amazing that theme developers do not include it as standard in their 404 landing pages.

The function works magic trying to process the given URL and figure out what post is actually required. You may have changed the structure of your permalinks but this function will figure out the new URL of the post if it is not too complicated. At least, you should include it every time just on an off-chance that it helps.

Add to the “functions.php” of your theme this snippet:

/*************************************************
 * Try to find the right page when it comes to 404
 */
function my_redirect_404() {
   if( is_404() ) {
     if ( $new_url = redirect_guess_404_permalink() ) {
       wp_redirect( $new_url );
       exit();
     }
   }
}
add_action( 'template_redirect', 'my_redirect_404' );

Most of redirects will then be automagically taken care of.… -->

continue reading →

Correcting the WordPress multisite URL when using domain mapping

I have come across a small problem in WordPress multisite. When using a mapping to a custom domain, the domain is apparently mapped but internally the site retains your main domain with a sub-domain as its address. So, while externally it may be “example.com”, internally it is still “example.mysite.net”. Usually, this does not cause any trouble but you may run into unexpected problems with more advanced stuff and some plugins may function incorrectly.

I came across this when trying to configure Facebook with Social Networks Auto-Poster (SNAP) plugin. The plugin will issue an OAuth request to Facebook but the request fails because the plugin uses the “example.mysite.net” instead of “example.com” as you would expect. So Facebook understandably rejects the request to authorize. And this same thing may happen in other places.

The site URL comes from the database, options “siteurl” and “home”. Fire up your favorite SQL tool and head for the database. Find your table wp_XX_options where the site in question is stored (XX being the id of the site, they simply get numbered from 1 up). Change the two options to the correct URLs and things should start looking up.

siteurl http://example.com
home http://example.com

Remember to change the URLs back to “example.mysite.net” when you remove the domain mapping.… -->

continue reading →

Getting WordPress cron work in multisite environment

There are several bits and pieces around that tell you how to get the WordPress cron work properly in simple situations. I just spent a morning getting it all working in a multisite environment so here come my notes on how to get it to work properly.

“Cron” is the scheduler of background tasks. You want to disable the built-in cron simulator when your site has the capability to run the normal UNIX cron jobs. The built-in simulator is quite unreliable and causes problems sooner or later. It is a good thing to have when the normal UNIX cron is not there but if you can install cron jobs you are better off with a standard reliable regular execution of your background tasks.

First of all, the usually advised first step is quite correct whatever the environment. You go to the installation directory, edit your wp-config.php and add the line before that last require_once statement (or anywhere in the middle of the file really) to disable the built-in cron simulator:

/* Disable wp-cron, we run linux cron */
define('DISABLE_WP_CRON', true);

Next, for a site that is not a network, i.e. not a multisite, it is sufficient to add something like this as a cron job:

*/2 * * * * www-data /usr/bin/php /var/www/yoursite/wp-cron.php > /dev/null )

This executes the cron of WordPress every two minutes. If you cannot run the command-line PHP for some reason but have wget (or any other thing, like lynx, curl, whatever) you can add a line to cron to call a URL instead, although that’s going to consume a tiny bit more resources:

*/2 * * * * www-data /usr/bin/wget -q -O - http://yoursite/wp-cron.php > /dev/null

Many recommend adding the parameter “doing_wp_cron” at the end of the URL but that is a mistake. Having that parameter assumes that you already acquired a lock for the cron job execution and may cause problems if you have long running jobs. Without that parameter, the wp-cron will do what it is supposed to do: acquire a lock so there is no contention, and then run its jobs.

For the multisite, however, it does not work so easily. You must execute the wp-cron for each and every of the “sites” in your network separately. This is kinda nuts but that’s how things are. There is no way to do that from a command line (as far as I can tell), so you have to call the URLs at each site.

I have the following script that reads the names of the sites and goes through… -->

continue reading →

WordPress Multisite – Getting the correct link to the site

The WordPress multisite install is a great thing. Except when you come across something that works not the way you expect.

So, the WordPress multisite installed on example.com with blogs on subdomain basis will give you sites with names like great.example.com and aruberusan.example.com. Of course, we all like nice looking domain names, so you install a mapping plugin and get the domain aruberusan.com map to your aruberusan.example.com and it all just works… So now you happily access your blog at aruberusan.com. Great. Until you run into trouble because internally your blog’s site address is still aruberusan.example.com. And the calls to get_site_url(), home_url(), admin_url() and so on still return you the old original name of your site before mapping, in my case the aruberusan.example.com.

This sucks and I could not find a solution to this weird problem. The only thing that came to mind was to use the actual site URL from the request and recompose the URL manually like this:

$adminurl = get_admin_url($path);
$admURL = parse_url($adminurl, PHP_URL_SCHEME) . "://" . 
    $_SERVER["SERVER_NAME"] . 
    parse_url($adminurl, $component = PHP_URL_PATH);

I would not call it a beautiful solution or even a proper one but it works. It is amazing that you cannot get the right URL from anywhere. Oh, and why you need it? Well, if you are going to post to, let’s say, Facebook, for example, with something like the SNAP plugin, you better have the right URL for your site or else…… -->

continue reading →

Automatic language tagging with Polylang in WordPress

I use the Polylang plugin for the multi-language capabilities of the sites written on WordPress. One feature that I implemented and find extremely useful is the automatic tagging of the posts with a language tag (like “en”, “ru”, etc.) when the post is saved. The code that goes into the functions.php file of the theme is as follows:

function tigra_add_polylang_language_tag( $post_id ) {
        global $polylang;
        if (isset($polylang) ) {
                if ( !$polylang->model->get_post_language($post_id) ) {
                        $polylang->model->set_post_language($post_id, pll_default_language());
                }
                $post_lang = $polylang->model->get_post_language($post_id);
                $languages = $polylang->model->get_languages_list(array('fields' => 'slug'));
                $post_tags = get_the_tags($post_id);
                $post_tags = wp_list_pluck($post_tags, 'name');
                $post_tags = array_diff($post_tags, $languages);
                if ( empty($post_tags) ) {
                        $post_tags = array();
                }
                array_push($post_tags, $post_lang->slug);
                wp_set_post_tags($post_id, $post_tags);
        }
}
add_action( 'save_post', 'tigra_add_polylang_language_tag' );

The code verifies that the default language is set (as I heard some reports that the mobile applications sometimes manage to bypass the Polylang capabilities) and sets it if necessary. Then, it extracts all tags from the post, wipes all supported (selected in Polylang configuration) language tags and adds a single tag corresponding to the language of the post.

This procedure makes sure that the language tag is always present and that the old tag is wiped when you change the language of the post. Now you can retrieve the posts, sort or do other manipulations based on the tag.

Big kudos to Chouby for the plugin and the help with code.… -->

continue reading →