Comment on Display Widgets SEO Plus Plugin by SEO Dave.

Display Widgets WordPress SEO Plus PluginIn the first release of the Display Widgets SEO Plus Plugin (v1.0.0) there was an issue with the WPML Plugin Widget Logic support (was a code bug).

The WPML plugin overrides the default WordPress get_categories() function (and other functions) so when say the Categories widget is loaded on a sidebar it ONLY loads categories from the language the user is viewing. So if in the German section of a site you only see German categories.

The problem with this is it overrides core WordPress functions which isn’t ideal, IMO they should have left the core WordPress functions like get_categories() alone and built their own custom functions which would only load specific languages etc… so it wouldn’t mess with how core WordPress works with other plugins.

As it is, the WPML language plugin changes how core WordPress functions work, so WordPress theme and plugin developers have to find workarounds.

In the Display Widgets SEO Plus Plugin (v1.0.0) I thought I’d added the correct workaround code (see earlier comment), BUT after more detailed testing there was a problem.

The WordPress Display Widgets SEO Plus transient (a cache of the get_categories() function) was acting in a weird way. I’d load a widget under “Appearance” > “Widgets” and open the “Categories +/-” form to see the correct categories. The correct Categories was ALL categories no matter what their language was.

However, upon clicking the Widgets “Save” button and reopening the “Categories +/-” form, it would only load the Categories of the language set on the WordPress Admin Bar!!!

I assumed I’d got the workaround code wrong (see earlier comment for the basic code).

The WPML plugin workaround code was incomplete for another reason (related to when the “WPML” > “Languages” : “Make themes work multilingual” – “Adjust IDs for multilingual functionality” option is ticked), but the basic workaround should have worked.

You would not believe how many things I tried to fix the code bug (over 8 hours of testing!!!!). I stripped the code right back so it no longer use a WordPress transient, even tried loading the Categories via the get_terms() function, nothing worked!

Eventually traced the issue back to another plugin function being called three times: this function self::register_globals(); is loaded three times in the original Display Widgets v2.05 plugin (in file display-widgets.php lines 256, 302 and 448).

Line 256 is the issue, I don’t know if it causes an issue on the original Display Widgets Plugin (v2.05), but in Display Widgets SEO Plus v1.0.0 it means when a widget is saved the WordPress transient is considered blank and is rebuilt using the get_categories() function WITHOUT the WPML language plugin workaround code.

In hindsight was an easy fix, delete one line of code :-) Though on the plus side spent so much time on this I’ve significantly improved how the transient is saved etc…, so not a complete waste of time.

Anyway, this is the WPML language plugin workaround code for getting ALL categories no matter what WPML language plugin options are set.

This is the Display Widgets SEO Plus Plugin v1.1.0 code

if ( class_exists( 'SitePress' ) ) {
  if ( empty( $this->cats ) ) {
    global $sitepress;
    remove_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ) );
    remove_filter( 'get_term', array( $sitepress,'get_term_adjust_id' ), 1 );
    remove_filter( 'terms_clauses', array( $sitepress,'terms_clauses' ) );
    $this->cats = get_categories( array(
      'hide_empty' => false,
    ) );
    add_filter( 'terms_clauses', array( $sitepress,'terms_clauses' ) );
    add_filter( 'get_term', array( $sitepress,'get_term_adjust_id' ) );
    add_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ), 10, 2 );
  }
} else {
  if ( empty( $this->cats ) ) {
    $this->cats = get_categories( array(
      'hide_empty' => false,
    ) );
  }
}

The above takes into account the categories are stored as a transient, so first checks if categories are available via the transient (code not show) hence the if ( empty( $this->cats ) ) { code.

If adding this sort of workaround to a plugin or theme start with this code:

if ( class_exists( 'SitePress' ) ) {
    global $sitepress;
    remove_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ) );
    remove_filter( 'get_term', array( $sitepress,'get_term_adjust_id' ), 1 );
    remove_filter( 'terms_clauses', array( $sitepress,'terms_clauses' ) );
    $allcategories = get_categories( array(
      'hide_empty' => false,
    ) );
    add_filter( 'terms_clauses', array( $sitepress,'terms_clauses' ) );
    add_filter( 'get_term', array( $sitepress,'get_term_adjust_id' ) );
    add_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ), 10, 2 );
} else {
    $allcategories = get_categories( array(
      'hide_empty' => false,
    ) );
}

The above code checks if the WPML plugin is active (checks for the “SitePress” class), if the plugin is active three WPML plugin filters are removed. The first two remove_filter are related to the “WPML” > “Languages” : “Make themes work multilingual” – “Adjust IDs for multilingual functionality” option (when ticked). The third remove_filter is for categories, tags, taxonomies functions.

When the filters are removed the get_categories() function gets ALL categories (stored in the $allcategories variable), then we add the WPML plugin filters back via the three add_filter code lines.

The } else { part is for when the WPML plugin isn’t active (when the “SitePress” class isn’t found). This grabs the categories in the normal way via the get_categories() function.

The above code works with the get_terms() function as well and assume the get_tags() (untested).

David Law