Archive for the ‘Bug Fixes’ category

WordPress SB Mail Attachment Widget Update (V1.1)

January 31st, 2012

A minor update today to improve the delivery efficiency of the emails with attachments. If you have no idea what this plugin is then check out my original post on it a few weeks ago here.

Some users were reporting issues with the email coming through as ignoring the HTTP headers and including all of them within the email itself. A big mess indeed. Now it uses the wp_mail command so it can be hooked into by other plugins. Also because of this function usage it means that I don’t need to write the headers manually.. WordPress does all that for you. It should now be a lot more compatible with the various mail clients.

Download it here: SB Mail Attachment Widget (2.7 kB)

How to fix the flaw in the WP Ecommerce table rate shipping module

January 25th, 2012

Catchy title eh! It’s difficult to name such a post but I have just diagnosed a client’s site and realised that there was a bit of an error in the WPEC (WPSC) table rate shipping module.

Reading the code it looks like the table rate module is designed to be used exclusively or in conjunction with a secondary service. The flaw I have found is that table rate is coded to always return a price regardless of whether you want one or not.

Basically my client wanted to use the weight shipping module for all postage except if the cart amount was more than £200 in which case free postage would be offered. Simple right?.. just add a layer (row) into the table rate settings with a minimum price of 200 and a value of 0. This would mean that weight based is used until the table rate conditional kicks in at £200 and offers cheaper postage (free in fact).

No.. sadly not correct :(

Table rate is written so that is always returns a price regardless of whether you want it to or not. Basically if you have a single row (layer) in the settings for the module it will show it. The system works well at the top end where price is greater than or equal to but there must always be a base price in the module (value of 0.00 or 0.01 if it doesn’t save) to catch those which fail the PHP logic. Note the following function to get a quote (taken directly from tablerate.php):

    function getQuote() {

        global $wpdb, $wpsc_cart;
        if (isset($_SESSION['nzshpcrt_cart'])) {
            $shopping_cart = $_SESSION['nzshpcrt_cart'];
        }
        if (is_object($wpsc_cart)) {
            $price = $wpsc_cart->calculate_subtotal(true);
        }

        $layers = get_option('table_rate_layers');

        if ($layers != '') {

            // At some point we should probably remove this as the sorting should be
            // done when we save the data to the database. But need to leave it here
            // for people who have non-sorted settings in their database
            krsort($layers);

            foreach ($layers as $key => $shipping) {

                if ($price >= (float)$key) {

                    if (stristr($shipping, '%')) {

                        // Shipping should be a % of the cart total
                        $shipping = str_replace('%', '', $shipping);
                        $shipping_amount = $price * ( $shipping / 100 );

                    } else {

                        // Shipping is an absolute value
                        $shipping_amount = $shipping;

                    }

                    return array("Table Rate"=>$shipping_amount);

                }

            }

            $shipping = array_shift($layers);

            if (stristr($shipping, '%')) {
                $shipping = str_replace('%', '', $shipping);
                $shipping_amount = $price * ( $shipping / 100 );
            } else {
                $shipping_amount = $shipping;
            }

            return array("Table Rate"=>$shipping_amount);

        }
    }

If you read through the code it basically loops through all of the layers to find the conditional price point that matches and returns the price. The oddity is the next set of code which, I suppose, is a fall back. Sadly the fall back is entirely unnecessary and causes this issue. The code starts from the following onwards:

$shipping = array_shift($layers);

In fact the simplest way to ‘fix’ the function is to put a return  statement just before that line:

return false;
$shipping = array_shift($layers);

Once that is in place you are free to use the module properly once again. I might write this as a separate shipping module for people to download as changing the name of each layer would be a nice idea as well as setting a maximum price point for each layer.

Turn off theme CSS for the visual editor in WordPress 3.3+

January 5th, 2012

It’s been on the cards for months and WordPress has finally added the inbuilt function whereby CSS files declared on the front end are now also declared on the edit item (post/page/custom post type) pages within the admin system. This is wonderful for some but, as someone who looks at a fair few sites using a range of free, premium and bespoke themes, actually it’s a curse in disguise. Let me explain…

Let’s say you go to the WordPress theme repository and grab a nice free theme which has been written by a developer less than ‘au fait’ with WordPress functionality or best practice. You turn on the theme, all looks good and then go to write a post only to be presented with the page from hell because loose CSS rules used in style.css have broken the editor page look and feel all together. As there is no way in CSS to set a priority without rewriting the code itself you are left with a mess.

Pre WordPress 3.3 this wasn’t an issue as you needed to explicitly declare an editor style sheet in order to use the styles and make it look somewhat closer to that which you might find on the front end of the site.

Now.. turning it off! Well it will require some coding and in actual fact the simplest way to do anything about it is to make your stylesheet invisible to WordPress. Let me explain: The correct way to enqueue any CSS and JS on your site is to do something like the following:

add_action('wp_print_styles', 'theme_add_stylesheet');
function theme_add_stylesheet() {
    wp_register_style('theme_stylesheet', get_stylesheet_directory_uri() . '/style.css');
    wp_enqueue_style( 'theme_stylesheet');
}

This means that when the wp_head action is triggered from header.php in your theme the style will be printed to screen along with the other styles and scripts. The enqueue style function adds the name and location of the script to a global array which can be reused at any time. In short, WordPress knows that it is a CSS file declared by a plugin or theme and therefore can reuse it at will.

The fix is simple.. don’t use that method and, instead, use the original crude method of adding a stylesheet which is to write the HTML yourself as follows:

<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />

This code, when placed in header.php of your theme, simply outputs the line in the head section of your page and includes the stylesheet unbeknown to WordPress and therefore won’t be used in the editor.

99% of the themes I have seen and used use the latter method so it’s not an issue but hopefully this will hel someone who has just upgraded and has some sort of multicoloured and wierdly laid out admin post page.

WordPress plugin queue jumping made easy

January 1st, 2012

Hi all. Happy new year etc.. I have plenty of plans for the next 12 months but won’t go into them unlike every other person with a blog is undoubtedly doing at the moment. I want to keep this strictly useful information and me telling you I want to shift some weight, buy something or do something isn’t going to improve your lives any really is it. So here goes..

I have had an interesting problem for some months now which I have just solved albeit crudely! I have written several plugins and released them into the WordPress plugin repository as regular readers of this site might already know. What you are unlikely to know though is that in doing so all you get is an influx of support questions. I personally like these.. it gives me the illusion of helping people out whilst really knowing that it should have been right to begin with :)

The worst of these aforementioned support questions are to do with plugin conflicts. Cue potential threads and threads about how the ‘other guy’ did something wrong which is going to need to poor user to go to their site/forum to get it sorted before our plugins can work in harmony as they were originally intended. This isn’t the best answer to a support question and certainly won’t get you any repeat custom. In all likelihood the user will ditch the plugin he finds least useful (yours.. after all he came to you to sort it in the first place meaning yours is likely the plugin they have just installed and are playing with) and install one of the other counterparts which undoubtedly does the same job but with umpteen donate buttons plastered all over it (I won’t go into that one right now but see my previous post for my thoughts on that particular subject).

One such example of a conflict I have been getting all year. It’s to do with my Welcome Email Editor plugin. WordPress does a fair few things very well indeed but sadly there are a few where it really could improve. This is why my Welcome Email Editor plugin exists at all. Can you guess what it does? Really? Ok so it lets you edit the WordPress welcome email.. the one that gives the user their user name and password if they decide to sign up for your site. The default offering is a little dull but luckily the guys who wrote WordPress have half heartedly thought about how it can be improved. Why let plugin writers like me do it of course. Sadly they opted not to use the action and filter system which already is ingrained in the rest of WordPress (for good reason I’m sure.. likely to do with load order) but instead just wrapped the entire wp_new_user_notification function in a PHP function called function_exists. This does what it says on the tin and only declares the function if someone else (a plugin or theme) doesn’t get there first.

In most cases this system works fine when you install a plugin dedicated to editing the welcome email and leave it at that. In reality most blogs have 30+ plugins active at any one time and probability and inevitability both say that more than one person is likely to want to jump on this handy feature for their plugin or theme. This means that one of the plugins needs to go! Normally if it were two plugins designed to edit the welcome email then we would be ok.. an obvious conflict of interest but what if one were a forum or shopping cart in conjunction with my plugin? Which goes then? Well the one which provides less functionality of course which, sadly, in that example would be my little plugin.

To make it somewhat more awkward, some plugins like to call WordPress core files directly thus causing the default function for the welcome email to be called before any other plugins and therefore chucking everyone else out of the race to declare the function first. Maintenance Mode is a plugin I know which does this when the system is active although it sorts itself out when you come out of maintenance mode so not really an issue. I have just been informed of another conflict with a plugin which makes dealing with WP Ecommerce in bulk easier (and we all know that was needed years ago!). Whatever reason they have called pluggable.php for I don’t know but it means that my plugin (or any other trying to declare a function first like this (it’s more common than you think!)) won’t function.

It’s such a simple solution but it works.. to fix you just need to rename my plugin directory to something else. WordPress naming conventions make calling a plugin anything starting with ‘WP’ very trendy indeed. My plugins are all prefixed SB, my initial, for archiving more than anything else but the people who do the same with initials AA are laughing at us all right now I assure you (or not laughing but living in blissful ignorance!). Here’s the logic.. it’s really simple:

On any given page load WordPress will load it’s core files first and then look for plugins to bolt on to the system using the action/filter system. This is where the PHP files are initially ‘required’/'included’ and individual balls (controlled by the plugin writers) set in motion. WordPress keeps a list of active plugins to call in the database in the wp_options table under an imaginatively named row called ‘active_plugins’. This is an alphabetically ordered list of plugins labelled by their location beneath the plugins directory (eg: welcome-email-editor/sb_welcome_email_editor.php). It will run from top to bottom including these files. This means there is a priority order for code defined only by the fact it has a name higher up the alphabet.

So to conclude the way to get your plugin run first to avoid conflicts with other plugins just put it in a directory called something beginning with a low alphabetical letter or special character. In my case I get a conflict every few months so it’s not worth changing but I am going to recommend that the next person to mention a conflict just renames their plugin folder from welcome-email-editor to -welcome-email-editor (note the leading hyphen). Job done!

I might add that changing the name of a plugin directory once a site is live isn’t a good idea on account of some plugins storing pathing information in the DB and WordPress itself storing the fact that plugin is active or not by it’s name in the directory tree. Put plainly if I change the name of my Welcome Email Editor plugin on my own site then it will deactivate itself and I shall need to reactivate it for it to continue working. Not a huge feat but try explaining that to normal user. Cue yet more support emails.

Hope this explains an issue for one or two of you. Perhaps plugin writers will learn not to call core PHP files directly in future to make my day run more smoothly… I doubt it!

Getting the WordPress Excerpt outside of The Loop

November 16th, 2011

I have been working my way around this one for a few months now, never bothering to think about the best solution. There is not, in fact, a WordPress simple function to get the excerpt outside of the WordPress loop. Why would you want to do that you ask…

Example:

I have a plugin I have written to create a basic shopping cart and shop front. It makes use of a simple shortcode on a Page to generate the shop which is based on a custom post type called Products. The Loop is used on the main page itself to generate the WordPress Page and subsequently process the shortcode. I loop through the products using a query_posts statement to bung the data into an array (for caching and manipulating so using a child Loop isn’t possible here) and then loop over it again later on. I want to show the Excerpt (which may or may not exist) on the shop front and the full description for my individual product pages.

So I initially thought of doing something like the following:

<?php
$product = get_page($product_id);
echo $product->post_excerpt;
?>

What this approach does wrong is returns nothing at all when the user hasn’t filled in an Excerpt for the product they entered. WordPress normally takes a selection of text from the main content, strips out any HTML and shortcodes and shows that instead.

Next option is this:

<?php
echo get_the_excerpt();
?>

What this does is prints the excerpt for the page which the shop front it hosted on (the parent page) because, as far as The Loop is concerned, the context of the page isn’t a shop front, it’s just a normal Page.

So why does this not work?

<?php
echo get_the_excerpt($product_id);
?>

Well some bright spark on a blog out in the ether thought it did however, regardless of what the argument for the function was initially, it no longer works as has been depracated (the argument that is).

So what’s the solution… well sadly it’s a custom function of your own. Luckily for you I have backtraced the code and writted my own little version of the above and it works a treat…

<?php
        function get_the_excerpt($id=false) {
            global $post;

            $old_post = $post;
            if ($id != $post->ID) {
                $post = get_page($id);
            }

            if (!$excerpt = trim($post->post_excerpt)) {
                $excerpt = $post->post_content;
                $excerpt = strip_shortcodes( $excerpt );
                $excerpt = apply_filters('the_content', $excerpt);
                $excerpt = str_replace(']]>', ']]&gt;', $excerpt);
                $excerpt = strip_tags($excerpt);
                $excerpt_length = apply_filters('excerpt_length', 55);
                $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');

                $words = preg_split("/[\n\r\t ]+/", $excerpt, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
                if ( count($words) > $excerpt_length ) {
                    array_pop($words);
                    $excerpt = implode(' ', $words);
                    $excerpt = $excerpt . $excerpt_more;
                } else {
                    $excerpt = implode(' ', $words);
                }
            }

            $post = $old_post;

            return $excerpt;
        }
?>

I have put mine in a class I used for my plugins these days as a helper function however just rename it (to avoid a naming conflict with it’s namesake) and call it from your plugin or theme as you would normally.

hope this helps someone out. Please let me know if anyone knows a better or simpler way. This works for me but I really wish there wasn’t such a monumental oversight by the WordPress guys on this one (other than creating sub loops which just feels wrong and inflexible to me)

WP Ecommerce template redirect

August 18th, 2011

Today I spent a good two to three hours making zero progress on a site which I was upgrading. I am making changes to the design but sadly didn’t get that far as first I decided to update WordPress and the plugins. The upgrade to WP 3.2.1 went well as did every other plugin except WP Ecommerce. I know this plugin to be a troublemaker but sadly as it’s the only half decent cart WordPress has to offer (and it’s pretty dire really).

The issue I was facing is that we have a custom page template for the shop to include a different sidebar and some other small changes. Upon upgrading the page template decided to revert to the theme’s page.php file instead of the template-shop.php we were using previously. Lots of head scratching and shouting followed and a couple of reverts from backups but eventually I got it down to a single function in the theme.functions.php file in the wpsc-includes directory. There are a couple of fixes you could use although the most straightforward is a hack to one of their core files… Sadly for me I don’t like doing that as the next time you upgrade you get to do it all over again. Luckily they had the foresight to add an action call at the top of the function so I wrote the following.

The Code

add_action('wpsc_swap_the_template', 'include_shop');

function include_shop() {
    global $wp_query,$wpsc_query;

    $products_page_id = wpec_get_the_post_id_by_shortcode('[productspage]');
    $term = get_query_var( 'wpsc_product_category' );
    $tax_term = get_query_var ('product_tag' );
    $obj = $wp_query->get_queried_object();
    $id = isset( $obj->ID ) ? $obj->ID : null;

    if( get_query_var( 'post_type' ) == 'wpsc-product' || $term || $tax_term || ( $id == $products_page_id )){

	$shop_template = trailingslashit(TEMPLATEPATH) . 'template-shop.php';
	require_once($shop_template);
	die;
    }
}

How to integrate it

To get this to work you just need to add it to your theme functions.php file and change where I have “template-shop.php” to be the name of your own template. This may well not even be an issue unless upgrading from an old version of WPSC but this fix worked for me.

As an aside I note the following comment left by one of the developers

// have to pass 'page' as the template type. This is lame, btw, and needs a rewrite in 4.0

Note: this was an issue when migrating from WP Ecommerce versions 3.7.7 to 3.8.6

SB Child List Update 1.2

June 19th, 2010

Just a quick one today… I have just checked in an update to the SB Child List plugin. It has been hugely popular with the WordPress community with only the one complaint to date… the reliance on the GUID field in the wp_posts table.

For some reason WordPress does not update this field often enough and it leads to broken links. I have updated the plugin to use the get_permalink function which I understand to work correctly in more recent versions of WordPress. I have also fixed a bug with the nesting level not saving correctly on the settings page.

Enjoy the release and please do let me know if you think the plugin can benefit from an update.

WordPress sites hosted by Rackspace Cloud hacked!

June 18th, 2010

I spent the best part of last night helping someone sort out their hacked sites. An interesting problem really… it’s a hack that has been effecting WordPress sites hosted with Rackspace Cloud and early speculation suggests it’s to do with an outdated version of PhpMyAdmin that someone had managed to break into. Rackspace have, apparently, been keeping quiet about it and have been logging into peoples servers and removing the appropriate files and records (so i’m told).

What does it do?

The hack causes a file to be uploaded to one of your plugin directories and masks itself as a language template file (pot). So far I have seen it hiding within All in one SEO pack and Si Captcha plugins but there are more! Within the file is a huge amount of garbage that looks to be rubbish. In actual fact it’s all valid php code but nonsense in the form of massive nested ternary IF statements using Hex codes as the condition and action parts. The point is, of course, to make the file look encrypted whilst actually masking a single function. This function simply calls a single row from the wp_options table, selects a portion of the data, reverses it runs it.

The second part of the hack is as follows… The database row that the above file decodes is stored on wp_options with an option_name of rss_ followed by a long number… again an attempt to make it look genuine. Within the row is a serialised string containing what looks like valid data but with a huge encoded section in the middle. To the trained eye it’s known to be a base64 encoded string, however, the twist is that the string and corresponding ‘eval’ statement are reversed and therefore running base64_decode won’t work out of the box.

When reversed and run, it’s a chunk of php with yet more base64 encoding inside but this time the correct way round! The end result is that it’s both a shell and a mysql browser allowing anyone knowing the correct URL parameters to gain access to both your file system and database(s).

Scary huh! Anything else…

Sadly yes! Most sites are reporting a new user in their users table with administrative rights sometimes called ‘amin’, other times having a … in it and other times completely hidden. I have read that the username is actually a huge amount of JS code which hides itself. Fairly clever to give the author of this hack credit where it’s due!

Next other sites are reporting some dodgy iFrames showing up in their posts. This is, apparently the extent of the problem however with complete access to your database and file structure they could be a lot more malicious.

Is there a fix?

Yep… Rackspace are, apparently, doing their best to fix the problem whilst not (at the time of writing and to my knowledge) taking responsibility for the problem. I am told that the site setup has been blamed and permissions of 777 have been mentioned. Again, all speculation so best go read up at more official sources.

So other than Rackspace sorting it you can do any of the following…

  • Remove any spurious rows from wp_options where there is a large encoded block in the value field. You should be looking for anything with an option name of rss_…. where … is a large number.
  • Remove the user ‘amin’ or anything with ‘…’ inside it from your database and change any passwords. The hack can NOT give the hacker your admin password so don’t worry but it’s best to change it just in case. There are always ways!
  • Check your plugin files for anything that looks odd. The file that I have seen has the ending .H.bak.pot or something similar. Bear in mind that .h is a library file, .bak is a text backup file and .pot is a language file. Neither .h nor .bak have any business on a WordPress site.

How can I stop this sort of thing from happening again?

You technically can’t but there are a couple of things to help you out…

  • Backup your site files and database regularly (where regularly is more frequent than once a month or just relying on your provider to do them!)
  • Turn off PHP commands like EXEC and EVAL. Anything that gives the PHP script access to your filesystem. It will definitely cause problems with plugins and sites but it’s the price we pay for safety
  • Make sure your permissions are all correct and check them regularly.
  • Check plugins before uploading them, a simple check in files for eval or exec should do it but it depends on how fussy you want to be!

That’s it for me… there are loads of blogs about detailing more about the problem and I understand the threat to be several days old now. Still worth knowing isn’t it!